Lenguaje de comandos para shell Unix. “Shell” en C: escribir un shell de comandos para Unix. intérprete de comandos c-shell

El shell del lenguaje de comandos (traducido como shell, shell) es en realidad un lenguaje de programación de muy alto nivel. En este idioma, el usuario controla la computadora. Normalmente, después de iniciar sesión, comienza a interactuar con el shell de comandos. Una señal de que el shell está listo para recibir comandos es el indicador que muestra en la pantalla. En el caso más sencillo es un dólar (“$”). Shell no es necesario y es el único lenguaje de comandos (aunque es el que está estandarizado en el marco de POSIX, el estándar de sistemas móviles). Por ejemplo, el lenguaje cshell es bastante popular; también existen kshell, bashell y otros. Además, cada usuario puede crear su propio lenguaje de comandos. Puede trabajar simultáneamente con diferentes lenguajes de comando en una instancia del sistema operativo. shell es uno de los muchos comandos de UNIX. Es decir, el conjunto de comandos "shell" incluye el comando "sh", que llama al intérprete "shell". El primer "shell" se llama automáticamente cuando inicia sesión y muestra un programador. Después de esto, puede llamar a cualquier comando para su ejecución, incluido el propio "shell", que creará un nuevo shell dentro del anterior. Entonces, por ejemplo, si prepara el archivo "archivo_1" en el editor:

Eco Hola!

entonces será normal archivo de texto, que contiene el comando "echo" que, cuando se ejecuta, muestra en la pantalla todo lo escrito a su derecha. Puede hacer que el archivo "file_1" sea ejecutable usando el comando "chmod 755 file_1". Pero se puede hacer llamando explícitamente al comando "sh" ("shell"):

Archivo sh_1

sh< file1

El archivo también se puede ejecutar en la instancia de shell actual. Hay un comando específico para este "." (punto), es decir

Archivo_1

Dado que UNIX es un sistema multiusuario, incluso puedes ordenador personal trabajar en paralelo en, digamos, 12 pantallas (cambiar de pantalla a pantalla ALT/tecla de función), teniendo en cada pantalla un usuario nuevo (o el mismo) con su propio shell de comandos. tu también puedes modo gráfico La ventana X también está abierta gran número windows, y cada ventana puede tener su propio usuario con su propio shell de comandos... El elemento central del lenguaje shell es el comando.

Estructuras de mando:

Los comandos en el shell suelen tener el siguiente formato:

<имя команды> <флаги> <аргумент(ы)>

Por ejemplo:

Ls -ls /usr/bin

Donde ls es el nombre del comando emisor directorio de contenidos, -ls - banderas ("-" - signo de banderas, l - formato largo, s - volumen de archivos en bloques), /usr/bin - directorio para el cual se ejecuta el comando Este comando mostrará el contenido del directorio. en formato largo /usr/bin, agregará información sobre el tamaño de cada archivo en bloques. Desafortunadamente, esta estructura de comando no siempre va seguida de un signo menos y las banderas no siempre incluyen comandos de una sola palabra. "Ejecutar" comandos como cc - llamar al compilador de lenguaje C, tar - trabajar con archivos, dd - copiar un archivo con conversión, buscar - buscar archivos y varios otros. Como regla general, el shell acepta la primera palabra. , como equipo. línea de comando

la primera palabra será descifrada por el shell como un comando (concatenación), que mostrará un archivo llamado "cat" (la segunda palabra) ubicado en el directorio actual. Redirección de comandos Entrada estándar (entrada): "stdin" en el sistema operativo UNIX se realiza desde el teclado del terminal, y salida estándar(salida): "stdout" se dirige a la pantalla del terminal. También hay un archivo de mensaje de diagnóstico estándar: "stderr", que se analizará un poco más adelante. Un equipo que puede trabajar con entrada estándar y la salida se llama FILTRO. El usuario dispone de medios convenientes para redirigir la entrada y salida a otros archivos (dispositivos). Los símbolos ">" y ">>" indican la redirección de salida.

ls >file_1 El comando "ls" generará una lista de archivos en el directorio actual y la colocará en el archivo "file_1" (en lugar de imprimirla en la pantalla). Si el archivo "file_1" existía antes, será sobrescrito por el nuevo.

Contraseña >>archivo_1 El equipo pwd se formará. nombre completo<" и "<<" обозначают перенаправление ввода.

directorio actual y lo colocará al final del archivo "file_1", es decir ">>" se agrega al archivo si no está vacío. Símbolos "

baño-l

contará y mostrará el número de líneas en el archivo file_1.<

Ed archivo_2<<" (т. е. "!"). То есть ввод будет закончен, когда первым в очередной строке будет "!". Можно сочетать перенаправления. Так

directorio actual y lo colocará al final del archivo "file_1", es decir ">>" se agrega al archivo si no está vacío. Símbolos " creará el archivo "file_2" usando el editor, directamente desde la terminal. El final de la entrada está determinado por el carácter de la derecha "

archivo_4

Wc -l >archivo_4

se realizan de la misma manera: se cuenta el número de líneas en el archivo "archivo_3" y el resultado se coloca en el archivo "archivo_4". El medio que combina la salida estándar de un comando con la entrada estándar de otro se llama PIPELINE y se indica mediante una barra vertical "|".

Se enviará una lista de archivos en el directorio actual a la entrada del comando "wc", que mostrará el número de líneas en el directorio. El pipeline también puede combinar más de dos comandos, cuando todos ellos, posiblemente excepto el primero y el último, son filtros:

Archivo de gato_1 | resultado grep -h | ordenar | gato -b > archivo_2

Esta canalización del archivo "file_1" ("cat") seleccionará todas las líneas que contengan la palabra "resultado" ("grep"), ordenará ("ordenar") las líneas resultantes y luego numerará ("cat -b") y imprima el resultado en el archivo "archivo_2". Como los dispositivos UNIX están representados por archivos especiales, se pueden utilizar en redirecciones. Los archivos especiales se encuentran en el directorio "/dev". Por ejemplo, "lp" - imprimir; "consola" - consola; "ttyi" - i-ésimo terminal; "nulo" es un archivo (dispositivo) ficticio (vacío). Entonces, por ejemplo,

Ls > /dev/lp

imprimirá el contenido del directorio actual y file_1< /dev/null обнулит файл "file_1".

Ordenar archivo_1 | camiseta /dev/lp | cola -20

En este caso, el archivo "file_1" se ordenará e imprimirá, y las últimas 20 líneas también se imprimirán en la pantalla. Volvamos a la redirección de salida. Los archivos estándar están numerados:

0 - entrada estándar, 1 - salida estándar 2 - stderr. Si no desea tener un mensaje de error en la pantalla, puede redirigirlo desde la pantalla al archivo que especifique (o desecharlo por completo redirigiéndolo al archivo de "dispositivo vacío" - /dev/null). Por ejemplo, al ejecutar el comando

Gato archivo_1 archivo_2

que debería mostrar el contenido de los archivos “archivo_1” y “archivo_2” secuencialmente en la pantalla, le dará, por ejemplo, lo siguiente

111111 222222 cat: f2: no existe tal archivo o directorio

donde 111111 222222 es el contenido del archivo "archivo_1" y falta el archivo "archivo_2", que el comando "cat" informó al archivo de diagnóstico estándar, de forma predeterminada, al igual que la salida estándar representada en la pantalla. Si no desea que aparezca ese mensaje en la pantalla, puede redirigirlo al archivo que especifique:

Gato archivo_1 archivo_2 2>f-err

Se enviarán mensajes de error (como lo indica la redirección "2>") al archivo "f-err". Por cierto, puedes enviar toda la información a un archivo "ff" usando en este caso diseño

Gato archivo_1 archivo_2 >>ff 2>ff

Puede especificar no sólo qué archivo estándar redirigir, sino también a qué archivo estándar redirigir.

Gato archivo_1 archivo_2 2>>ff 1>&2

Aquí, primero se redirige "stderr" (en modo de adición) al archivo "ff", y luego la salida estándar se redirige a "stderr", que en este punto es el archivo "ff". Es decir, el resultado será similar al anterior. La construcción "1>&2" significa que además del número del archivo estándar al que redirigir, debes poner "&" delante; toda la estructura está escrita sin espacios.<- закрывает стандартный ввод. >- cierra la salida estándar. Archivos de comando. Hay varias opciones para permitir que un archivo de texto se utilice como comando. Usemos un editor para crear un archivo llamado "cmd" que contenga una línea como esta:

Fecha; pwd; es

Puede llamar al shell como un comando, denominado "sh", y pasarle un archivo "cmd" como argumento o como entrada redirigida, es decir.

$shcmd

$sh

El resultado de ejecutar cualquiera de estos comandos será la fecha, luego el nombre del directorio actual y luego el contenido del directorio. Una opción más interesante y conveniente para trabajar con un archivo por lotes es convertirlo en ejecutable, es decir. simplemente conviértalo en un comando, lo cual se logra cambiando el código de seguridad. Para hacer esto, debe permitir la ejecución de este archivo. Por ejemplo,

Mod 711 cmd

creará el código de seguridad "rwx__x__x". Entonces una simple llamada

ejecutará los mismos tres comandos. El resultado será el mismo si el archivo con el contenido

Fecha; pwd; es

se representa en la forma: fecha pwd ls ya que la transición a otra línea también es un separador en la secuencia de comandos. Por lo tanto, los archivos ejecutables pueden ser no solo archivos obtenidos como resultado de la compilación y el ensamblaje, sino también archivos escritos en el lenguaje Shell. Se ejecutan en modo interpretación utilizando un intérprete de shell.

Depuración de archivos por lotes

SHELL utiliza dos mecanismos para depurar archivos por lotes. El primero es: set -v imprime las líneas del archivo de comando a medida que se leen. Este modo se utiliza cuando se buscan errores de sintaxis. Para usarlo, no necesita modificar el archivo de comando, por ejemplo: sh -v proc... aquí proc es el nombre del archivo de comando. El modificador -v se puede utilizar junto con el modificador -n, que evita la ejecución de comandos posteriores (el comando set -n bloquea el terminal hasta que se ingresa el indicador EOF). El comando set -x muestra los comandos a medida que se ejecutan, y las líneas del programa se envían al terminal y sus valores se sustituyen en lugar de las variables. Para cancelar los modificadores -x y -v, puede usar el comando set - y para instalar, asigne el valor correspondiente a una variable macro. ENTORNO SHELL (VARIABLES Y PARÁMETROS) En el lenguaje Shell, puede escribir archivos por lotes y usar el comando "chmod" para hacerlos ejecutables. Después de esto, no se diferencian de otros comandos del sistema operativo UNIX.

variables de shell

El nombre de una variable de shell es una secuencia de letras, números y guiones bajos que comienzan con una letra. El valor de una variable de shell es una cadena de caracteres. El hecho de que sólo haya dos tipos de datos en el shell: una cadena de caracteres y un archivo de texto, por un lado, facilita la participación en la programación de usuarios finales que nunca antes han hecho programación y, por otro lado, provoca una cierta protesta interna entre muchos programadores que están acostumbrados a una diversidad significativamente mayor y una mayor flexibilidad de medios lingüísticos. Sin embargo, es interesante observar cómo los programadores altamente calificados, familiarizados con las "reglas del juego" del shell, escriben programas en él muchas veces más rápido que en C, pero, lo que es especialmente interesante, en algunos casos estos programas funcionan incluso más rápido que los implementados en C. Un nombre de variable es similar a la idea tradicional de un identificador, es decir el nombre puede ser una secuencia de letras, números y guiones bajos, comenzando con una letra o un guión bajo. El operador de asignación "=" se puede utilizar para asignar valores a variables.

Var_1=13 - "13" no es un número, sino una cadena de dos dígitos.

var_2="SO UNIX" - Aquí se requieren comillas dobles (" ") porque hay un espacio en la cadena.

También son posibles otras formas de asignar valores a las variables del shell. Por ejemplo, la grabación

hace que el comando "fecha" se ejecute primero (las comillas invertidas indican que el comando adjunto debe ejecutarse primero), y el resultado de su ejecución, en lugar de enviarse a la salida estándar, se asigna como el valor de una variable, en este caso "DAT". También puede asignar un valor a una variable usando el comando "leer", que garantiza que el valor de la variable se reciba desde la pantalla (teclado) en modo de diálogo. Por lo general, el comando "leer" en el archivo por lotes va precedido del comando "eco", que le permite mostrar previamente algún mensaje en la pantalla. Por ejemplo:

Echo -n "Ingrese un número de tres dígitos:" lea x

Al ejecutar esta parte del archivo de comando, después de que se muestre el mensaje

Ingrese un número de tres dígitos:

el intérprete se detendrá y esperará a que se ingrese un valor desde el teclado. Si ingresó, digamos, "753", este se convertirá en el valor de la variable "x". Un comando de "lectura" puede leer (asignar) valores a varias variables a la vez. Si hay más variables en "leer" de las ingresadas (separadas por espacios), a las restantes se les asigna una cadena vacía. Si hay más valores transmitidos que variables en el comando "leer", los adicionales se ignoran. Al acceder a una variable de shell, debe preceder el nombre con el símbolo "$". Entonces los comandos echo $var_2 echo var_2 se mostrarán en la pantalla

Sistema operativo UNIX var_2 Escapando

Echemos un vistazo más de cerca a las técnicas de escape utilizadas en el caparazón. Las comillas dobles (" "), las comillas simples (" ") y la barra invertida (\) se utilizan como dispositivos de escape. Su acción se desprende claramente de los ejemplos: puedes escribir varias tareas en una línea.

X=22 y=33 z=$x A="$x" B="$x" C=\$x D="$x + $y + $z" E="$x + $y + $z " F=$x\ +\ $y\ +\ $z

(la asignación G=$x+$y fallaría debido a los espacios) Entonces

Eco A = $A B = $B C = $C eco D = $D E = $E F = $F eco de evaluación evaluado A = $A eco de evaluación evaluado B = $B eco de evaluación evaluado C = $C

Se mostrará en la pantalla.

A = 22 B = $x C = $x D = 22 + 33 + 22 E = $x + $y + $z F = 22 + 33 + 22 evaluado A = 22 evaluado B = 22 evaluado C = 22

Demos algunos ejemplos más relacionados con los cambios de línea de escape. Deje que a la variable "cadena" se le asigne el valor de una "matriz" de 2x3: abc def Tenga en cuenta que para evitar asignar espacios adicionales, la segunda línea de la matriz comienza desde la primera posición de la siguiente línea: cadena="abc def" Luego hay tres opciones para escribir la variable en el comando echo "echo" $string echo "$string" echo "$string" dará respectivamente tres resultados diferentes: abc def $string abc def y la secuencia de comandos echo "str_1 str_2" > file_1 echo "str_1 str_2" > file_2 cat file_1 file_2 generará archivos secuencialmente idénticos file_1 y file_2: str_1 str_2 str_1 str_2 Tenga en cuenta también que la barra invertida (\) no solo escapa el carácter que le sigue, lo que permite utilizar caracteres especiales de forma sencilla como caracteres que se representan a sí mismos (también puede escapar de sí mismo - \\), pero en un archivo de comando, una barra invertida le permite concatenar líneas en una (escapar del final de la línea. Por ejemplo, el ejemplo de línea de comando dado anteriormente:

Archivo de gato_1 | resultado grep -h | ordenar | gato -b > archivo_2

podría escribirse en un archivo por lotes, digamos como

Archivo de gato_1 | grep -h\resultado | ordenar | gato -b > archivo_2

Por cierto, el símbolo del transportador también proporciona el efecto de continuar la línea de comando. En este caso, podría dar un resultado mejor, como este:

Archivo de gato_1 |

resultado grep -h |

ordenar |

gato -b > archivo_2

Manipulaciones con variables de shell A pesar de que las variables de shell generalmente se perciben como cadenas, es decir, "35" no es un número, sino una cadena de dos caracteres "3" y "5", en algunos casos se pueden interpretar de manera diferente. por ejemplo como números enteros. El comando "expr" tiene una variedad de capacidades. Ilustremos algunos con ejemplos: Ejecutar un archivo por lotes:

X=7 y=2 a=`expr $x + $y` ; eco a=$a a=`expr $a + 1`; echo a=$a b=`expr $y - $x` ; echo b=$b c=`expr $x "*" $y` ; echo c=$c d=`expr $x / $y` ; echo d=$d e=`expr $x % $y` ; eco e=$e

se mostrará en la pantalla

Se mostrarán números en la pantalla que muestran el número de caracteres coincidentes en las cadenas (desde el principio). La segunda línea no puede ser más larga que la primera:

4 0 0 0

Exportación de variables El sistema operativo UNIX tiene el concepto de proceso. Un proceso ocurre cuando se ejecuta un comando. Por ejemplo, al escribir "p" en el teclado Se genera el "proceso "p". A su vez, "p" puede generar otros procesos. Supongamos que "p" llama a "p1" y "p2", que generan secuencialmente los procesos correspondientes. Cada proceso tiene su propio entorno: un conjunto de variables disponibles. Por ejemplo, antes de ejecutar "p", ya había un entorno en el que ya estaban definidas algunas variables. Al iniciar "p" se genera un nuevo entorno "p1" y "p2" ya se generará en él; Las variables son locales del proceso en el que se declaran, es decir, donde se les asignan valores. Para que estén disponibles para otros procesos generados, se deben pasar explícitamente el comando incorporado "exportar". se utiliza.

Opciones

EN archivo por lotes Se pueden pasar parámetros. El shell utiliza parámetros posicionales (es decir, el orden en que aparecen es importante). En el archivo de comando, las variables correspondientes a los parámetros (similares a las variables del shell) comienzan con el símbolo "$", seguido de uno de los números del 0 al 9: Llame a "examp-1" con los parámetros "cock" y "cola". Estos parámetros van al nuevo entorno con los nombres estándar "1" y "2". La variable (estándar) denominada "0" almacenará el nombre del cálculo llamado. Al acceder a los parámetros, el número está precedido por el símbolo del dólar "$" (como al acceder a las variables): $0 corresponde al nombre de este archivo de comando; $1 es el primer parámetro en orden; $2 segundo parámetro, etc. Dado que el número de variables a las que se pueden pasar parámetros está limitado a un dígito, es decir 9º (“0”, como ya se señaló, tiene un significado especial), luego, para transferir una mayor cantidad de parámetros, se utiliza un comando especial “shift”. El comando "set" proporciona un enfoque único a los parámetros. Por ejemplo, fragmento

Establecer a b con eco primero=$1 segundo=$2 tercero=$3

gato -b > archivo_2

Primero=a segundo=b tercero=c

aquellos. el comando "set" establece los valores de los parámetros. Esto puede resultar muy conveniente. Por ejemplo, el comando "fecha" muestra la fecha actual, diga "lunes 01 de mayo 12:15:10 2000", que consta de cinco palabras, luego

Establecer `fecha` eco $1 $3 $5

gato -b > archivo_2

lun 01 2000

El comando "set" también le permite controlar la ejecución del programa, por ejemplo: las líneas set -v se envían al terminal y el shell las lee. set +v cancela el modo anterior. set -x imprime comandos en la terminal antes de la ejecución. set +x cancela el modo anterior. El comando "set" sin parámetros muestra el estado del entorno del software en el terminal.

Sustituciones de conchas

Antes de interpretar y ejecutar directamente comandos contenidos en archivos de comandos, el shell realiza varios tipos de sustituciones: 1. SUSTITUCIÓN DE RESULTADOS. Todos los comandos entre comillas se ejecutan y el resultado se sustituye en su lugar. 2. SUSTITUCIÓN DE VALORES DE PARÁMETROS Y VARIABLES. Es decir, las palabras que comienzan con "$" se reemplazan con los valores correspondientes de variables y parámetros. 3. INTERPRETACIÓN DE BRECHAS. Los espacios escapados se ignoran. 4. GENERACIÓN DE NOMBRES DE ARCHIVOS. Se comprueba la presencia de caracteres especiales en las palabras ("*", "?"") y se realizan las generaciones correspondientes. Entorno de software Cada proceso tiene un entorno en el que se ejecuta. Shell utiliza varias de estas variables de entorno. Si escribe el comando "establecer" sin parámetros, la pantalla mostrará información sobre una serie de variables estándar creadas al iniciar sesión (y luego transmitidas a todos sus nuevos procesos "heredados"), así como las variables creadas y exportadas por sus procesos. . El tipo específico y el contenido de la información resultante depende en gran medida de qué versión de UNIX se utiliza y cómo está instalado el sistema.

Resultado de la ejecución establecer comandos sin parámetros (no completo):

HOME=/root PATH=/usr/local/bin:/usr/bin:/bin:.:/usr/bin/X11: IFS= LOGNAME=sae MAIL=/var/spool/mail/sae PWD=/home/ sae/ESTUDIO/SHELL PS1=$(PWD):" " PS2=> SHELL=/bin/bash

Comentemos los valores de las variables. HOME=/root es el nombre del directorio de inicio donde termina el usuario después de iniciar sesión. Es decir, habiendo ingresado correctamente el nombre y la contraseña, me encontraré en el directorio “/root”. PATH=/bin:/usr/bin:.:/usr/local/bin:/usr/bin/X11: esta variable especifica la secuencia de archivos que el shell busca en busca de un comando. Los nombres de los archivos están separados aquí por dos puntos. El orden de visualización corresponde al orden de los nombres en el recorrido. Pero inicialmente la búsqueda se produce entre los llamados comandos integrados. Los comandos integrados incluyen los comandos más utilizados, como "echo", "cd", "pwd", "date". Después de esto, el sistema busca en el directorio “/bin”, que puede contener los comandos “sh”, “cp”, “mv”, “ls”, etc. Luego el directorio "/usr/bin" con los comandos "cat", "ss", "expr", "nroff", "man" y muchos otros. A continuación, la búsqueda se realiza en el directorio actual ("".", u otra designación "vacío", es decir, ""), donde probablemente se encuentren los comandos que escribió. Después de escribir la línea de comando y presionar "shell" (después de realizar las sustituciones necesarias) reconoce el nombre correspondiente al comando y lo busca en los directorios enumerados en PATH. Si el comando se coloca fuera de estos directorios, no se encontrará. Si hay varios comandos con el mismo nombre, se llamará al que se encuentre en el directorio visto primero. PATH, al igual que otras variables, se puede cambiar fácilmente agregando, reorganizando o eliminando directorios. IFS= (Separador de campos interno) enumera caracteres que sirven para separar palabras (campos). Estos son "espacio", "tabulación" y "avance de línea", por lo que aquí no se ve nada a la izquierda de la tarea y dos líneas están ocupadas. LOGNAME=root - nombre de inicio de sesión (“nombre de usuario”). MAIL=/var/spool/mail/root: el nombre del archivo en el que se recibe el correo (correo electrónico). PWD=/root - nombre del directorio actual PS1=$(PWD):" " - tipo de directorio. En este caso, el indicador mostrará el nombre del directorio actual seguido de dos puntos y un espacio. Es decir, habrá "/root:". PS2=>: este mensaje (aquí ">") se utiliza como una invitación para continuar ingresando (en la siguiente línea) un comando sin terminar. Por ejemplo, escriba el corchete de apertura "(" y después de presionar V siguiente línea Verá este indicador. Si no sabe qué hacer a continuación, escriba el corchete de cierre ")" y desaparecerá. SHELL=/bin/sh: esta variable especifica el shell que está utilizando el usuario. En este caso, se utiliza el shell estándar ("sh"). El entorno inicial se instala automáticamente al iniciar sesión utilizando archivos como "/etc/rc" y "/etc/.profile". Una forma de cambiar simplemente el entorno (por ejemplo, ruta de búsqueda de comandos, tipo de programa, tipo de shell, color de pantalla, etc.) es colocar esta información en su directorio de inicio en un archivo ".profile" especializado ($(HOME)/ . perfil), asignando valores requeridos variables de entorno. Es decir, llama este archivo al editor y escribe lo que quieras). Luego, cada vez que inicie sesión, este archivo se ejecutará automáticamente e instalará un nuevo entorno. Este archivo DEBE colocarse en su directorio INICIO(directorios de entrada). Debe tenerse en cuenta que los nombres de archivos que comienzan con un punto generalmente tienen un estado especial. Por lo tanto, no se muestran en la pantalla con un simple comando "ls"; debe llamar a este comando con el indicador "-a". Por cierto, no son destruidos indiscriminadamente por el comando “rm *”. El propio intérprete de shell asigna automáticamente valores a las siguientes variables (parámetros): ? el valor devuelto por el último comando; $ número de proceso; ! número de proceso en segundo plano;

  1. el número de parámetros posicionales pasados ​​al shell;
  • lista de parámetros como una línea;

@ lista de parámetros, como un conjunto de palabras; - banderas pasadas al caparazón. Al acceder a estas variables (es decir, al usarlas en un archivo de comando, programa shell), debe poner "$" delante. Un papel importante en la creación de archivos únicos lo desempeña la variable especial "$$", cuyo valor corresponde al número del proceso que realiza este cálculo. Cada nuevo cálculo realizado por una computadora inicia uno o más procesos que reciben números automáticamente en orden. Por lo tanto, al utilizar el número de proceso como nombre de archivo, puede estar seguro de que cada archivo nuevo tendrá un nombre nuevo (no se escribirá en lugar de uno existente). La ventaja es también la principal desventaja de este método de nombrar archivos. No se sabe qué nombres se asignarán a los archivos. Y si dentro este proceso puedes encontrar un archivo “sin mirar”, es decir, accediendo a él usando $$, entonces dichos archivos se pueden perder fácilmente. Esto crea problemas adicionales al depurar programas. Llamar al intérprete Después de registrar al usuario en el sistema (usando el comando de inicio de sesión), se llama al intérprete del lenguaje SHELL. Si el directorio de registro del usuario contiene un archivo .profile, antes de recibir al menos un comando desde la terminal, el intérprete ejecuta este archivo (se supone que el archivo .profile contiene comandos). Al llamar, se pueden especificar las siguientes claves: -c cadena Los comandos se leen de la cadena dada. -s Los comandos se leen desde la entrada estándar. Los mensajes del intérprete se escriben en un archivo de diagnóstico estándar. -i Modo de funcionamiento interactivo. Si el primer carácter del parámetro "0" es un signo, entonces los comandos se leen desde el archivo .profile.

ESTRUCTURAS DEL PROGRAMA===

Como en cualquier lenguaje de programación, el texto del shell puede contener comentarios. Para ello se utiliza el símbolo "#". Todo lo que está en la línea (en el archivo de comando) a la izquierda de este carácter es percibido por el intérprete como un comentario. Por ejemplo,

# Este es un comentario.

Como cualquier lenguaje de programación procedimental, el lenguaje shell tiene operadores. Varios operadores le permiten controlar la secuencia de ejecución del comando. En tales operadores, a menudo es necesario verificar la condición, que determina la dirección en la que continúan los cálculos.

Comando prueba ("")

El comando de prueba verifica que se cumpla una determinada condición. Las declaraciones de bucle y selección del lenguaje Shell se generan utilizando este comando (integrado). Dos posibles formatos de comando:

Condición de prueba

[ condición ]

Usaremos la segunda opción, es decir En lugar de escribir la palabra "prueba" antes de la condición, incluiremos la condición entre paréntesis, lo cual es más común para los programadores. De hecho, el shell reconocerá este comando por el corchete de apertura "[" como una palabra, correspondiente al comando"prueba". Debe haber espacios entre los corchetes y la condición que contienen. También debe haber espacios entre los valores y el símbolo de comparación u operación. El shell utiliza condiciones de varios "tipos". CONDICIONES DE VERIFICACIÓN DE ARCHIVOS: -f archivo archivo "archivo" es un archivo normal; -d archivo archivo "archivo" - directorio; -с archivo archivo "archivo" es un archivo especial; -r archivo tiene permiso para leer el archivo "archivo"; -w el archivo tiene permiso para escribir en el archivo "archivo"; -s archivo el archivo "archivo" no está vacío.

CONDICIONES PARA PROBAR CADENAS: str1 = str2 las cadenas "str1" y "str2" coinciden; str1 != str2 las cadenas "str1" y "str2" no son iguales; -n cadena str1 "str1" existe (no vacía); -z str1 la cadena "str1" no existe (vacía). Ejemplos.

X="quién es quién"; exportar x; [ "quién es quién" = "$x" ]; eco $?

0x=abc; exportar x ; [abc = "$x"]; eco $?

0x=abc; exportar x ; [-n "$x"]; eco $?

0x=""; exportar x ; [-n "$x"]; eco $?

1

Además, hay dos valores de condición estándar que se pueden usar en lugar de condición (no se necesitan paréntesis para esto). CONDICIONES PARA COMPARAR ENTEROS: x -eq y "x" es igual a "y", x -ne y "x" no es igual a "y", x -gt y "x" es mayor que "y", x - ge y "x" es mayor o igual a "y", x -lt y "x" menor que "y", x -le y "x" menor o igual a "y". CONDICIONES COMPLEJAS: Implementado usando operaciones lógicas estándar: ! (no) invierte el valor del código de salida. -o (o) coincide con el "O" lógico. -a (y) coincide con el "Y" lógico.

Declaración condicional "si"

En general, la declaración "si" tiene la estructura

Si la condición entonces lista

Aquí "elif" se puede utilizar una versión abreviada de "else if" junto con la versión completa, es decir. Se permite el anidamiento de un número arbitrario de declaraciones "si" (así como otras declaraciones). Por supuesto, la “lista” en cada caso debe ser significativa y aceptable en el contexto dado. La estructura más truncada de este operador.

Si la condición entonces lista fi

si se cumple la condición (generalmente aquí es donde se recibe el código de finalización "0"), entonces se ejecuta la "lista", de lo contrario se omite. Ejemplos: escriba "if-1".

Si [ $1 -gt $2 ]

luego pwd else echo $0: ¡Hola!

Luego, llamar a if-1 12 11 producirá /home/sae/STUDY/SHELL y if-1 12 13 producirá if-1: ¡Hola!

Aquí "case", "in" y "esac" son palabras funcionales. La "cadena" (puede ser un solo carácter) se compara con el "patrón". A continuación se ejecuta la "lista de comandos" de la línea seleccionada. El ";;" al final de las líneas de selección parece inusual, pero escriba ";" sería un error. Se pueden ejecutar múltiples comandos para cada alternativa. Si estos comandos están escritos en una línea, entonces el símbolo ";" se utilizará como separador de comandos. Normalmente, la última línea de selección tiene el patrón "*", que en la estructura "caso" significa "cualquier valor". Esta línea se selecciona si el valor de la variable (aquí $z) no coincide con ninguno de los patrones escritos previamente delimitados por el corchete ")". Los valores se ven en el orden en que fueron escritos.

Operador de bucle enumerado ("for")

El operador de bucle "for" tiene la estructura:

por nombre

do lista de comandos realizados donde "for" es una palabra auxiliar que define el tipo de bucle, "do" y "done" son palabras auxiliares que resaltan el cuerpo del bucle. Deje que el comando "lsort" esté representado por un archivo por lotes

Para i en file_1 file_2 file_3 haga proc_sort $he terminado

En este ejemplo, el nombre "i" actúa como parámetro de bucle. Este nombre se puede considerar como una variable de shell a la que se asignan secuencialmente los valores enumerados (i=archivo_1, i=archivo_2, i=archivo_3) y el comando "proc_sort" se ejecuta en un bucle. A menudo se utiliza la forma "para i en *", que significa "para todos los archivos en el directorio actual". Deje que "proc_sort" a su vez esté representado por un archivo por lotes

Gato $1 | ordenar | camiseta /dev/lp > $(1)_sorted

aquellos. ordenados secuencialmente archivos especificados, los resultados de la clasificación se imprimen ("/dev/lp") y se envían a los archivos file_1_sorted file_2_sorted y file_3_sorted

Declaración de bucle con condición verdadera ("mientras")

La estructura "mientras", que también realiza cálculos, es preferible cuando se desconoce de antemano. lista exacta Los valores de los parámetros o esta lista deben obtenerse como resultado de cálculos en un bucle. La instrucción del bucle " while " tiene la estructura:

mientras condición

lista de comandos realizados donde "mientras" es una palabra auxiliar que determina el tipo de bucle con una condición verdadera. La lista de comandos en el cuerpo del bucle (entre "do" y "done") se repite siempre que la condición siga siendo verdadera (es decir, el código de salida último comando en el cuerpo del bucle es "0") o el bucle no será interrumpido internamente por comandos especiales ("interrumpir", "continuar" o "salir"). Cuando ingresa al ciclo por primera vez, la condición debe ser verdadera. El comando "break [n]" le permite salir de un bucle. Si falta "n", equivale a "interrupción 1". "n" indica el número de bucles anidados de los que salir, por ejemplo, "romper 3" - salir de tres bucles anidados. A diferencia del comando "interrumpir", el comando "continuar [n]" solo detiene la ejecución del ciclo actual y regresa al COMIENZO del ciclo. También puede ser con un parámetro. Por ejemplo, "continuar 2" significa salir al comienzo del segundo bucle anidado (contando desde la profundidad). El comando "exit [n]" le permite salir del procedimiento por completo con un código de retorno de "0" o "n" (si se especifica el parámetro "n"). Este comando se puede utilizar en más que solo bucles. Incluso en secuencia lineal comandos, puede ser útil durante la depuración detener el cálculo (actual) en un punto determinado.

Declaración de bucle con condición falsa ("hasta")

El operador de bucle "hasta" tiene la estructura:

hasta la condición

lista de comandos realizados donde "hasta" es una palabra auxiliar que determina el tipo de bucle con una condición falsa. La lista de comandos en el cuerpo del bucle (entre "hacer" y "hecho") se repite hasta que la condición sigue siendo falsa o el bucle no es interrumpido desde el interior por comandos especiales ("romper", "continuar" o "salir"). "). La primera vez que ingresa al bucle, la condición no debería ser verdadera. La diferencia con el operador " while " es que se verifica que la condición del bucle no sea falsa (para un código de salida distinto de cero del último comando del cuerpo del bucle) y se verifica DESPUÉS de cada (¡incluida la primera!) ejecución de comandos en el cuerpo del bucle. Ejemplo.

Hasta que sea falso

lea x si [$x = 5] entonces haga eco lo suficiente; romper si no hacer eco un poco más fi

Aquí el programa está en un bucle infinito esperando que se ingresen palabras (repitiendo la frase "algo más" en la pantalla) hasta que se ingresa "5". Después de esto, se emite "suficiente" y el comando "interrumpir" deja de ejecutar el bucle.

Operador vacío

La declaración vacía tiene el formato

:

No hace nada. Devuelve el valor "0".

Funciones en shell

La función le permite preparar una lista de comandos de shell para su posterior ejecución. La descripción de la función es la siguiente:

Nombre() (lista de comandos)

después de lo cual la función se llama por su nombre. Cuando se ejecuta la función, no se crea ningún proceso nuevo. Se ejecuta en el entorno del proceso correspondiente. Los argumentos de la función se convierten en sus parámetros posicionales; el nombre de la función es su parámetro cero. Puede interrumpir la ejecución de una función utilizando el operador "return [n]", donde (opcional) "n" es el código de retorno.

Manejo de interrupciones ("trampa")

Puede ser necesario proteger la ejecución del programa contra interrupciones. La mayoría de las veces encontrará las siguientes interrupciones correspondientes a las señales: 0 salida del intérprete, 1 colgar (desconexión del abonado remoto), 2 interrupción del , 9 destrucción (no interceptado), 15 fin de ejecución. Para protegerse contra interrupciones, existe un comando "trampa", que tiene el formato:

Trampa de señales de "lista de comandos"

Si ocurren interrupciones en el sistema, cuyas señales se enumeran separadas por un espacio en las "señales", entonces se ejecutará la "lista de comandos", después de lo cual (si el comando "salir" no se ejecutó en la lista de comandos) el control Regrese al punto de interrupción y la ejecución del archivo de comando continuará. Por ejemplo, si necesita eliminar archivos en "/tmp" antes de interrumpir la ejecución de un archivo de comando, puede hacerlo con el comando "trap":

Trampa "rm /tmp/*; salida 1" 1 2 15

que precede a otros comandos en el archivo. Aquí, después de eliminar los archivos, se cerrará el archivo de comando.

Seguramente casi todos los lectores de Habr conocen los shells sh y bash. Además, la mayoría de nosotros hemos oído algo sobre zsh y tcsh. Sin embargo, la lista de shells existentes no termina ahí. Se pueden dividir a grandes rasgos en tres grupos:

  • Clones de shell Bourne (bash, zsh)
  • C shell (csh, tcsh)
  • Basado en lenguajes de programación populares (psh, ipython, scsh)
  • Exótico, específico y todo lo demás.
Se discutirán los más interesantes de ellos.

El propósito de escribir este artículo no fue revisar o clasificar todos los shells de comandos existentes. solo quiero hablar de algunos productos interesantes en esta área, ampliar los horizontes del lector. Me alegraré. si esto anima a alguien a estudiar el tema con más detalle o incluso a pasar a otro tema.
Primero, brevemente sobre qué es. Un shell de comandos o intérprete de comandos es una aplicación que proporciona al usuario una interfaz de línea de comandos en la que el usuario ingresa comandos individualmente o ejecuta scripts que constan de una lista de comandos. Oralmente y en textos no oficiales a menudo se le llama "shell", del inglés shell - shell.

Los shells compatibles con POSIX más utilizados descienden del shell Bourne, así que comenzaremos con eso.

Bourne Shell y sus clones.

concha de bourne, archivo ejecutable: sh. Un shell de comandos que lleva el nombre de su creador, Stephen Bourne. Mayoría operadores fue tomado por él del lenguaje ALGOL 68 Publicado en la séptima edición del operativo. Sistemas UNIX, donde estaba el shell predeterminado. Hasta el día de hoy, la gran mayoría de sistemas tipo Unix tienen /bin/sh, un enlace físico o simbólico a un shell compatible con sh.

Bourne Shell otra vez, archivo ejecutable: intento. El título puede traducirse como “El paseo renacido de Bourne”. Probablemente el caparazón más popular en la actualidad. Estándar de facto para Linux. No me detendré en ello, porque... hay mucho en internet buenos articulos sobre fiesta. Por ejemplo aquí y aquí.

concha Z, archivo ejecutable: zsh. Un shell gratuito y moderno compatible con SH. Tiene una serie de ventajas sobre bash relacionadas principalmente con trabajar en modo interactivo. Escribieron sobre esto en Habré y
Además, hay bastantes proyectiles que entran en este grupo: el proyectil Korn (ksh) y el proyectil Almquist (ash), etc., pero no nos detendremos en ellos en detalle.

caparazón C

caparazón C, archivo ejecutable: csh Un shell de comando desarrollado por el autor de vi, Bill Joy. Como base para lenguaje de secuencias de comandos csh fue tomado, como su nombre indica, del lenguaje C. en aquel momento, en 1978, era el lenguaje de programación más popular entre los desarrolladores y usuarios de BSD UNIX. EN momento presente mas popular implementación gratuita csh-tcsh.

Carcasa TENEX C, archivo ejecutable: tcsh. Fue en tcsh donde apareció por primera vez el autocompletado. Este es el shell predeterminado en FreeBSD. Puedes leer más al respecto.
Para mostrar claramente la diferencia en la sintaxis, daré varios ejemplos de scripts que hacen lo mismo para csh y un intérprete de comandos compatible con sh.

Construcción condicional:

Un bucle que calcula las primeras 10 potencias de dos:

#!/bin/sh i=2 j=1 mientras [ $j -le 10 ]; hacer echo "2 **" $j = $i i=`expr $i "*" 2` j=`expr $j + 1` hecho #!/bin/csh establecer i = 2 establecer j = 1 mientras ($j<= 10) echo "2 **" $j = $i @ i *= 2 @ j++ end

Sin embargo, la lista de características admitidas por las últimas versiones de bash, zsh y tcsh es muy similar y la elección de un shell específico es principalmente una cuestión de gustos. Con conchas menos comunes la situación es diferente. Aquí las diferencias son más significativas.

Shells de comandos basados ​​en lenguajes de programación populares.

Shell Perl, archivo ejecutable: psh. Un shell que combina las características de los shells anteriores y el poder del lenguaje Perl. Porque psh está escrito en perl e incluso puede ejecutarse en Windows. Algunos ejemplos de uso de psh:
ls | s/y/k/ # Reemplazo usando expresiones regulares ls | ( print ++$i, ": $_"; )q # Filtro rápido. Dentro de las llaves hay una expresión Perl donde $_ contiene una línea de salida.

netstat | ( $_>2; )g # filtros grep. Solo se imprimen aquellas líneas para las cuales la expresión entre paréntesis devuelve verdadero comando >[=FOO] # Redirigir a un descriptor de archivo abierto comando > archivo # Equivalente al comando 2> archivo en bash. Redirige la salida y el flujo de error a un archivo grep foo lib/**/*.pm # Usando **, lo que significa el directorio actual y todos los subdirectorios scsh , archivo ejecutable scsh . Intérprete de comandos con fuente abierta usando como guión Lenguaje del esquema 48. No admite funciones estándar para otros shells (historial de comandos, edición de texto en la línea de comandos, agregar rutas/comandos). Se recomienda el uso de secuencias de comandos, pero no para trabajo interactivo . Puede atraer a los aficionados. programación funcional
. A continuación se muestra un ejemplo de un script que muestra los nombres de todos los archivos ejecutables ubicados en directorios de la variable de entorno PATH.

#!/usr/local/bin/scsh -s !# (definir (directorio de ejecutables) (con-cwd dir (filtrar archivo-ejecutable? (directorio-archivos dir #t)))) (definir (writeln x) (mostrar x) (nueva línea)) (para cada escritura (ejecutables de mapa adjunto ((infix-splitter ":") (getenv "RUTA")))) IPython . Este es un shell interactivo para el idioma. Programación en Python , que tiene una serie de funciones adicionales. IPython tiene perfil especial
para funcionar como un shell de comandos del sistema. La forma de iniciar este modo depende, según tengo entendido, de la versión, pero en mi máquina se ve así:

ipython3 --perfil=pysh

  • Ya se ha escrito bastante sobre IPython, incluso en ruso (enlaces al final del artículo). Intentaré enumerar sus características principales desde el punto de vista de su uso como shell de comandos:
  • Multiplataforma. Incluso existe una versión para Windows.
  • Versiones de Python 2.x o 3.x como lenguaje de programación, capacidades de introspección mejoradas Autocompletar código pitón
  • así como nombres de archivos y comandos del sistema.
  • Historial de comandos y macros basadas en él.
Un mecanismo que agiliza la navegación por catálogos, marcadores y mucho más Como puede ver, en términos de capacidades interactivas, IPython es al menos tan bueno como bash. En cuanto a los scripts, IPython será conveniente para quienes conocen que bash. De hecho, los scripts de IPython se diferenciarán de Python puro sólo en la llamada simplificada de los comandos del sistema. A continuación se muestran algunos ejemplos de la integración de Python y los comandos del sistema:
# Digamos que queremos calcular el tamaño total de los archivos de registro dpkg: Entrada: cd /var/log/ /var/log Entrada: log_files = !ls -l dpkg.log* Entrada: log_files Salida: "-rw-r- -r-- 1 raíz raíz 1824 3 de noviembre 16:41 dpkg.log" Entrada: para línea en log_files: ....: tamaño += int(line.split()) ....: Entrada: tamaño Salida: 1330009 # ..o hacer ping secuencialmente a diez hosts In: for i in range(100,110): ....: !ping -c 1 192.168.0.$i ....:
Descansar
Por supuesto que no lo es lista completa incluso conchas populares. Además de las categorías anteriores, también existen aquellas que utilizan su propia sintaxis, que no es compatible con sh y no copia el lenguaje existente. Un ejemplo sería el amigable caparazón interactivo (pez). Pero, por último, no me gustaría hablar de eso, sino de un Sleepshell más específico.

Chupete para dormir, archivo ejecutable: sueño. Estrictamente hablando, a Sleepshell no se le puede llamar procesador de comandos, porque no puede procesar comandos. Y, en general, no puede hacer nada excepto escribir periódicamente asteriscos "*" en la salida estándar. Sin embargo, se usa precisamente como shell de comandos y por esta razón: Digamos que queremos darle a alguien la oportunidad de hacer túneles ssh a través de nuestro servidor ejecutando Linux o Unix. Lea más sobre los túneles ssh. Pero no necesitamos que alguien tenga acceso a la línea de comandos y al sistema de archivos de nuestro servidor. Sleepshell está diseñado para tal caso. Creamos una cuenta en el servidor como shell e instalamos sleepshell para ella. El propietario de la cuenta podrá conectarse y reenviar puertos, pero no podrá ejecutar comandos.

Eso es todo. Espero que haya sido interesante. Estaré encantado de recibir cualquier comentario y consejo sobre el texto del artículo.

Enlaces relacionados
www.faqs.org/faqs/unix-faq/shell/shell-differences - tabla resumen de diferencias y similitudes de shell
www.mariovaldez.net/software/sleepshell - Sleep Dummy Shell
ipython.org/ipython-doc/dev/interactive/shell.html - IPython como shell del sistema
www.opennet.ru/base/dev/ipython_sysadmin.txt.html - Shell IPython como herramienta administrador del sistema

¿Qué es un caparazón y por qué es necesario?

El shell de comandos en cualquier sistema tipo Unix, incluido GNU/Linux, es un programa normal que se ejecuta tanto en una consola de texto (que se usa cada vez menos) como en un entorno gráfico, en la ventana de un emulador de terminal, disponible en cualquier sistema Linux.

Su tarea es simple y obvia: aceptar una línea (o líneas) de entrada, producirlas analizando y, según los resultados de este análisis, reaccionar en consecuencia: ejecutar un comando, ejecutar un programa, mostrar un mensaje de diagnóstico, etc.

Casi todos Distribuciones de Linux Para los usuarios, el shell de comandos predeterminado es bash (Bourne Again SHell es otro shell de comandos de Bourne; Steve Bourne es el autor del primer shell de comandos en Unix: sh). De hecho, se ha convertido en un estándar no oficial y sus mejoras funcionalidad continúa continuamente. Hay otros shells de comando: tcsh ( Versión C-shell), ksh (Korn Shell), zsh, etc. – cada uno tiene sus propias ventajas y desventajas, así como sus propios grupos de fans. Sin embargo, bash es más familiar para una amplia gama de usuarios con diferentes niveles de experiencia, razón por la cual lo elegí. También vale la pena señalar que, independientemente de las capacidades que tengan los distintos caparazones, todos son compatibles con su progenitor ideológico: el Bourn Shell (sh). En otras palabras, un script escrito para sh funcionará correctamente en cualquier shell moderno (lo contrario generalmente no ocurre).

Beneficios de la línea de comando

Puede surgir la pregunta: ¿por qué molestarse con la línea de comandos si existen interfaces gráficas cómodas y hermosas? Hay muchas razones para esto. En primer lugar, no todas las operaciones son más cómodas y rápidas de realizar utilizando una interfaz gráfica. En segundo lugar, cada programa sigue el principio fundamental de los sistemas Unix: hacer un trabajo bien definido y hacerlo bien. En otras palabras, siempre comprenderá lo que sucede cuando ejecuta una utilidad en particular (si algo no está del todo claro, debe consultar el manual). En tercer lugar, al dominar los comandos, probar sus combinaciones y combinaciones de sus parámetros, el usuario estudia el sistema y adquiere valiosos experiencia practica. Obtiene acceso a herramientas poderosas como canalizaciones que le permiten organizar una cadena de comandos para el procesamiento de datos, herramientas de redirección de E/S y, además, puede programar directamente en shell de comando. Quizás valga la pena detenerse en la programación con más detalle, especialmente porque muchos scripts del sistema en Linux (por ejemplo, scripts para iniciar servicios del sistema) están escritos para el shell.

Shell de comandos como lenguaje de programación

Entonces, el shell de comandos puede considerarse como un lenguaje de programación y como entorno de software ejecución simultáneamente. Por supuesto, este lenguaje no se compila, sino que se interpreta. Permite el uso de variables: del sistema o propias. La secuencia de ejecución de los comandos del programa se cambia utilizando construcciones de verificación de condiciones y seleccionando la opción apropiada: if-then-else y case. Los bucles while, Until y for le permiten automatizar acciones repetitivas. Es posible combinar grupos de comandos en bloques lógicos. Incluso puedes escribir funciones reales que les pasen parámetros. Por lo tanto, están disponibles todas las características y características de un lenguaje de programación completo. Intentemos sacar el doble beneficio de esto: además de aprender los conceptos básicos de programación, automatizaremos nuestro trabajo diario.

¡Hola Mundo! Sistema de respaldo sencillo

Sobre la necesidad de regular respaldo Todo el mundo conoce los datos, pero los usuarios nunca tienen tiempo suficiente para esta aburrida operación. La solución es sencilla: organizar la creación automática de copias de seguridad. Esta será nuestra primera tarea de programación de shell.

#!/bin/bash # # Copia de seguridad de directorios y archivos desde el directorio de inicio # Este script por lotes se puede ejecutar automáticamente usando cron # cd $HOME if [ ! -d archivos] luego mkdir archivos fi cur_date=`fecha +%Y%m%d%H%M` if [$# -eq 0]; luego tar czf archive$(cur_date).tar.gz proyectos bin else tar czf archive$(cur_date).tar.gz $* fi if [ $? = 0 ] ; luego mv archive$(cur_date).tar.gz $HOME/archives echo "$cur_date – Copia de seguridad completada exitosamente". else echo "$cur_date - ERROR durante la copia de seguridad". fi

Cualquier script de comando (el script es un script, como se llama a los programas de shell de comandos) comienza con una línea de identificación, en la que se especifica explícitamente el intérprete de comandos, indicando la ruta completa al mismo. La ruta completa es una lista secuencial de todos los directorios, comenzando desde la raíz, que se deben ingresar para llegar al archivo de destino y, por supuesto, el nombre de este archivo. Registrar la ruta completa es extremadamente importante para identificar de forma única cada archivo en la jerarquía del sistema de archivos.

Siguen cuatro líneas de comentarios. Tan pronto como el shell encuentra el carácter "#", considera todos los caracteres siguientes como comentarios y los ignora por completo hasta el final. línea actual. Por lo tanto, puede iniciar un comentario no desde el principio de la línea, sino acompañarlo con algún comando.

Después de los comentarios hay una línea vacía. No significa nada para el shell de comandos y no se realiza ninguna acción. En escenarios lineas vacias Generalmente se inserta para hacer que el código del programa sea más fácil de leer.

Finalmente llegamos al primer equipo "real". Le permite cambiar el directorio (Cambiar directorio), es decir. pasar del directorio actual a otro pasado al comando como argumento. En la mayoría de los casos, el directorio de destino se especifica explícitamente, por ejemplo, cd /tmp o cd proyectos, pero en nuestro caso se utiliza la variable de sistema predefinida HOME: contiene la ruta completa al directorio de inicio del usuario actual bajo cuyo nombre Se está ejecutando el script de comando. Esto elimina la necesidad de realizar cambios de código cada vez que cambiamos de usuario, porque el comando devuelve a todos a su directorio personal. El signo de dólar "$" delante del nombre de una variable significa que debe extraer el valor contenido en esa variable y sustituirlo en lugar de su nombre en la línea de comando. Cabe señalar especialmente que en lenguaje de comando Las carcasas de letras son importantes, es decir. INICIO, Hogar y hogar son tres variables diferentes. Por convención, las letras mayúsculas indican los nombres de las variables del sistema: INICIO, RUTA, EDITOR, etc. Esta convención no impide que los usuarios creen sus propias variables con nombres en mayúsculas, pero ¿por qué complicarse la vida rompiendo las reglas y regulaciones? Tampoco se recomienda cambiar los valores de las variables del sistema a menos que sea absolutamente necesario. En general, seguimos una regla simple: usamos variables del sistema para fines de solo lectura y, si necesitamos las nuestras, escribimos su nombre en letras minúsculas.

Nuestro primer comando podría escribirse más brevemente:

discos compactos ~

Aquí el símbolo "~" también significa el directorio de inicio del usuario actual. Los veteranos de la línea de comando lo expresan de manera aún más sucinta:

CD

La idea es que cuando el comando cd no recibe ningún argumento, cambia al directorio de inicio.

El siguiente paso es el diseño de software clásico para verificar las condiciones y tomar la decisión adecuada. Esquema general Es esto:

si<условие>entonces<одна или несколько команд>fi

La última palabra de la construcción (si está en orden inverso) actúa como paréntesis de cierre, es decir límites de la lista de comandos ejecutados cuando la condición es verdadera. La presencia de fi es obligatoria, incluso si solo hay un equipo en la lista.

Para verificar una condición, por regla general, se utiliza el comando de prueba o su forma alternativa de notación entre corchetes. En otras palabras, registros

si [! -d archivos] si prueba! -d archivos

absolutamente equivalente. prefiero corchetes, ya que definen más claramente los límites de la condición que se está probando. Tanto el paréntesis derecho como el izquierdo deben estar separados de la condición por espacios.

Los criterios para comprobar el estado están determinados por varias banderas. El comando de prueba reconoce una lista muy grande de ellos. En nuestro ejemplo, se utiliza el indicador -d, que nos permite comprobar si el nombre especificado después del indicador corresponde a un directorio real. Las siguientes opciones se utilizan con mayor frecuencia cuando se trabaja con archivos:

F – si existe un archivo normal con el nombre de pila;

R – si el archivo especificado tiene derecho a leerlo;

W – si el archivo especificado tiene derecho a escribir en él;

X – si el archivo especificado tiene derecho a ejecutarlo;

S: si el archivo especificado tiene un tamaño distinto de cero.

En nuestro caso, la condición está precedida por signo de admiración, que denota la operación de negación lógica, por lo que el significado de la condición que se está probando se vuelve completamente opuesto. Intentemos escribir el significado de estos comandos en ruso común:

si [! -d archivos] Si el directorio de archivos (en el directorio actual) no existe, comience a ejecutar el bloque de comandos: mkdir archivos crea el directorio de archivos (en el directorio actual) y finalice la ejecución del bloque de comandos.

Como puede ver, todo resultó no ser tan complicado. Con un poco de práctica, usted mismo podrá leer y crear fácilmente diseños similares. El comando de creación de directorio es tan obvio que no se requieren más explicaciones.

En la siguiente línea creamos nuestra propia variable local, cur_date. En la gran mayoría de los casos, las variables se crean simplemente asignando un valor específico, por ejemplo:

ten=10 string="Esta es una línea de texto"

Pero en nuestro ejemplo se aplica pequeño truco. Tenga en cuenta que después del signo igual, el símbolo de asignación, el comando está escrito entre comillas invertidas. Esta forma de notación le permite asignar a una variable no la cadena en sí, sino el resultado de su ejecución. Aquí está el resultado del comando de fecha, que devuelve la fecha y hora actuales en un formato especificado por una lista de parámetros:

%Y – año actual en forma completa, es decir de cuatro dígitos (por ejemplo, 2009);

%m – número del mes actual (por ejemplo, 09 – para septiembre);

%d – número del día actual;

%H – hora actual en formato de 24 horas;

%M – minuto actual.

Por lo tanto, si ejecuta el comando

cur_date=`fecha +%Y%m%d%H%M`

el diez de septiembre de 2009 a las 22:45, a la variable cur_date se le asignará el valor de cadena "200909102245". El propósito de este truco es crear un nombre único y no repetitivo para el archivo comprimido. Si tiene la intención de ejecutar varias instancias del programa en un minuto, puede mejorar la unicidad de los nombres agregando los segundos actuales. ¿Cómo? Estudie el manual de la utilidad de fecha (fecha de hombre); no tiene nada de complicado.

Antes de comenzar a crear un archivo de almacenamiento, debemos determinar qué directorios guardaremos en él. Para mayor flexibilidad, podemos especificar un conjunto de directorios para archivar de forma predeterminada, pero brindar la posibilidad de reemplazar este conjunto con una lista de directorios pasados ​​como argumento a nuestro script de comando. Para este propósito, se utilizan variables de shell de comando especiales: $# – el número de parámetros pasados ​​al script y $* – todos los parámetros pasados, escritos en formato de una línea.

si [$# -eq 0]; entonces

Verificando la condición "si el número de parámetros pasados ​​es cero", luego ejecute el siguiente comando. Tenga en cuenta que palabra clave luego se puede escribir en la línea de condición, separándola de la expresión condicional con un punto y coma.

tar czf archive$(cur_date).tar.gz contenedores de proyectos

El comando para crear un archivo de almacenamiento y comprimir este archivo. La utilidad tar en sí no realiza la compresión, solo recopila todo archivos especificados y directorios en un único archivo tar. La primera bandera está destinada a esto: c (crear). La compresión realiza programa externo– aquí está gzip, llamado por la segunda bandera - z. Si tiene instalado en su sistema el programa de compresión bzip2, más eficiente, puede aprovecharlo modificando el comando de la siguiente manera:

tar cjf archive$(cur_date).tar.bz2 contenedores de proyectos

La tercera bandera f indica que lo que sigue es el nombre del archivo comprimido, por lo que siempre es el último en la lista de banderas. Tenga en cuenta que al sustituir, el nombre de la variable se escribe entre llaves. Esto se hace para resaltar explícitamente la variable en la línea que la rodea, eliminando así muchos problemas potenciales. Las extensiones no se asignan al archivo comprimido automáticamente; usted mismo agrega todo lo que necesita. He especificado proyectos y bin como directorios predeterminados para archivar, pero puedes escribir los nombres de tus directorios más valiosos aquí.

La palabra clave else abre una rama de ejecución alternativa. Los comandos de este bloque comienzan a funcionar si la verificación de condición devuelve el resultado "falso" (en nuestro ejemplo: "el número de parámetros pasados ​​no es cero", es decir, los nombres de directorio especificados por el usuario). En este caso el comando se verá así:

archivo tar czf$(cur_date).tar.gz $*

Aquí los directorios predeterminados se reemplazan por una cadena de nombre de directorio aceptada externamente. Es posible aceptar y procesar cada parámetro externo por separado, pero es más conveniente para nosotros pasar la cadena completa.

Al final del programa, se realiza otra verificación. En entornos Unix, todos los comandos devuelven un código de estado de finalización. Si el comando fue exitoso, devuelve el código 0; de lo contrario, el código de salida será distinto de cero. Para comprobar el éxito del comando de archivado anterior, usaremos otra variable especial $?, que siempre contiene el valor del código de finalización del comando más reciente. Si en la variable $? contiene 0, es decir El archivo de copia de seguridad se creó correctamente, luego lo movemos al directorio de archivo:

mv archivo$(cur_date).tar.gz $HOME/archivos

y mostrar el mensaje correspondiente:

echo "$cur_date – La copia de seguridad se completó correctamente."

Si la verificación muestra que el código de finalización de la operación de archivado no es cero, se muestra un mensaje de error:

echo "$cur_date - ERROR durante la copia de seguridad."

Esto completa nuestro script de comando.

Para probar el funcionamiento de nuestro programa, necesitamos guardar el código fuente descrito anteriormente en un archivo, por ejemplo, llamado bckp, y luego, por conveniencia, hacerlo ejecutable:

chmod 750 bckp

y ejecuta:

./bckp

para crear una copia de seguridad de los directorios predeterminados, y

./bckp docs progs funciona

para crear una copia de seguridad de los directorios enumerados (especifique los nombres de los directorios que realmente existen en su sistema; de lo contrario, recibirá un mensaje de error).

Puede colocar el archivo bckp en uno de los directorios especificados en el sistema. variable RUTA. Las ubicaciones más preferidas son /usr/local/bin o $HOME/bin si las tiene. Después de esto, puedes ejecutar bckp como comando del sistema.

Cómo automatizar las operaciones de copia de seguridad programadas

Algunas palabras sobre la automatización de copias de seguridad. Para ello, se utiliza el programador cron del sistema, que lee las instrucciones de trabajo de un archivo crontab especial. Para definir dichas instrucciones, necesita crear y editar su archivo crontab usando el comando:

crontab-e

Las instrucciones están escritas en un formato estrictamente definido (los campos están separados por espacios):

minutos horas día_del_mes mes día_de_la semana comando

Una opción para programar operaciones de respaldo podría verse así:

30 23 10,20,30 * * /usr/local/bin/bckp

Esto significa que el script de copia de seguridad (debe proporcionar la ruta completa a este archivo) se ejecutará a las 23:30 los días 10, 20 y 30 de cada mes, independientemente del día de la semana. (Los asteriscos indican todo el rango de valores permitidos, en este caso: cada mes - en el 4º campo, cualquier día de la semana - en el 5º campo)

Si prefiere resumir sus resultados por semana y su sistema funciona las 24 horas del día, los 7 días de la semana, entonces tiene sentido programar copias de seguridad durante las horas de menor actividad:

0 5 * * 3.5 /usr/local/bin/bckp

Aquí copias de seguridad se creará a las 5:00 los miércoles y viernes de cada mes (asterisco en el 4º campo), independientemente de la fecha (asterisco en el 3º campo).

Puede leer sobre todas las complejidades de la programación en hombre manual 5 crontab.

Resultados y conclusiones

El script de copia de seguridad que se analiza en este artículo tiene propiedades funcionales modestas. Pero ese no era su punto. tarea principal, sino para que el lector comprenda lo que se puede hacer en la línea de comando, y no solo copie y ejecute el archivo de comando propuesto, sino que se interese en ampliar sus funciones y comience a explorar las inmensas posibilidades que brindan los shells de comandos. Y si alguien, después de leer este artículo, intenta mejorar el código proporcionado aquí, escribe su propia versión o implementa su propia idea independiente, entonces consideraré que se ha logrado el objetivo principal.

Recursos para descargar

static.content.url=http://www.site/developerworks/js/artrating/

ID del artículo=458335

ArticleTitle=Conceptos básicos de programación de Shell

  • Tutorial

¿Por qué y para quién es el artículo?

Inicialmente, esto fue un recordatorio para los estudiantes que comienzan a trabajar con sistemas tipo Unix. En otras palabras, el artículo está destinado a aquellos que no tienen experiencia previa trabajando con la línea de comandos de Unix, pero por una razón u otra quieren o necesitan aprender cómo interactuar efectivamente con ella.

No se volverá a contar mana (documentación) y el artículo no cancela ni reemplaza de ninguna manera su lectura. En cambio, hablaré sobre las cosas principales (comandos, técnicas y principios) que debes comprender desde el principio de trabajar en shell unix para que el trabajo se desarrolle de manera eficiente y placentera.

El artículo trata sobre entornos completos tipo Unix, con un shell completamente funcional (preferiblemente zsh o bash) y una gama bastante amplia de programas estándar.

que es la concha

Shell (shell, también conocido como “línea de comando”, también conocido como CLI, también conocido como “consola”, también conocido como “terminal”, también conocido como “ventana negra con letras blancas”) es interfaz de texto comunicación con el sistema operativo (bueno, estrictamente hablando, esto es programa, que proporciona dicha interfaz, pero ahora esta diferencia es insignificante).

En general, trabajar a través de un shell se ve así: el usuario (es decir, usted) ingresa un comando desde el teclado, presiona Enter, el sistema ejecuta el comando, escribe el resultado de la ejecución en la pantalla y nuevamente espera el siguiente comando. para ser ingresado.

Tipo de caparazón típico:

El shell es la forma principal de interactuar con todos los sistemas de servidor tipo Unix.

¿Dónde se encuentran los sistemas de línea de comando?

Donde un shell Unix podría estar esperándote, opciones populares:
  • MacOS (golpe);
  • acceso remoto al servidor para trabajar o para un proyecto web personal;
  • servidor de archivos doméstico con acceso remoto;
  • Ubuntu, PC-BSD en una computadora portátil/de escritorio: los sistemas similares a Unix hoy en día son fáciles de instalar y usar.

¿Qué problemas es razonable resolver con un caparazón?

Tareas naturales para las que la concha es apta, útil e indispensable:
  • trabajo interactivo en la terminal:
    • realizar compilación, ejecutar trabajos mediante make;
    • comparación de archivos de texto;
    • análisis rápido de datos ad-hoc (número de IP únicas en el registro, distribución de registros por horas/minutos, etc.);
    • acciones masivas únicas (eliminar muchos procesos; si trabaja con un sistema de control de versiones, revertir o resolver un montón de archivos);
    • diagnóstico de lo que está sucediendo en el sistema (semáforos, bloqueos, procesos, descriptores, espacio en disco, etc.);
  • secuencias de comandos:
    • scripts de instalación, para los cuales no puede confiar en la presencia de otros intérpretes; esto no es para principiantes;
    • las funciones para personalizar el shell interactivo (que afectan la invitación, cambiar el directorio, configurar variables de entorno) tampoco son exactamente para principiantes;
    • secuencias de comandos únicas, como la grabación masiva de archivos;
    • archivos make.

Absolutamente primeros pasos

Comencemos: iniciar sesión y cerrar sesión

Asegúrese de saber exactamente cómo iniciar el shell y cómo salir de él.

Si está trabajando en una máquina con Ubuntu instalado, debe iniciar el programa Terminal. Cuando termine, simplemente puede cerrar la ventana.

En MacOS, inicie también Terminal.

Para acceder servidor remoto- use ssh (si tiene MacOS, Ubuntu u otro sistema similar a Unix localmente) o PuTTY (si tiene Windows).

¿Quién soy, dónde estoy?

Ejecute los siguientes comandos:
  • nombre de host: muestra el nombre de la máquina (servidor) en la que se encuentra actualmente;
  • whoami: muestra su inicio de sesión (su nombre en el sistema);
  • tree -d / |less - representación pseudográfica del árbol de directorios en la máquina; salir del desplazamiento -q;
  • pwd: muestra el directorio en el que se encuentra actualmente; en la línea de comando no puedes estar “así”, debes estar en algún directorio (=directorio actual, directorio de trabajo). El directorio de trabajo actual probablemente se muestre en su mensaje.
  • ls: lista de archivos en el directorio actual; ls /home - lista de archivos en el directorio especificado;

Historial de comandos (historial)

Una propiedad importante de una línea de comando completa es el historial de comandos.

Ejecute varios comandos: nombre de host, ls, pwd, whoami. Ahora presione la tecla arriba. El comando anterior aparece en la línea de entrada. Puede utilizar las teclas arriba y abajo para avanzar y retroceder en el historial. Cuando llegue al nombre de host, presione Entrar; el comando se ejecutará nuevamente.

Los comandos del historial no sólo se pueden ejecutar repetidamente, sino también editarlos. Desplácese por el historial hasta el comando ls, agréguele el modificador -l (resulta que ls -l , hay un espacio antes del signo menos, pero no después). Presione Enter; se ejecutará el comando modificado.

Desplazarse por el historial, editar y volver a ejecutar comandos son las acciones más comunes cuando se trabaja en la línea de comandos, así que acostúmbrate.

Copiar y pegar

La línea de comando está muy centrada en el texto: los comandos son texto, los datos de entrada para la mayoría de los programas estándar son texto y la salida suele ser texto.

Lo mejor del texto es que se puede copiar y pegar, y esto también se aplica a la línea de comandos.

Pruebe el comando fecha +"%y-%m-%d, %A"
¿Lo ingresó completamente a mano o lo copió del artículo? Asegúrate de poder copiarlo, pegarlo en una terminal y ejecutarlo.

Una vez que haya aprendido a usar man, asegúrese de poder copiar y ejecutar comandos de ejemplo desde la ayuda. Para comprobarlo, busque la sección EJEMPLOS de la ayuda del programa de fechas, copie y ejecute el primer ejemplo proporcionado (por si acaso: el. El signo de dólar no forma parte del comando; esta es una imagen simbólica de un mensaje de entrada).

Cómo copiar exactamente el texto del terminal y pegarlo en el terminal depende de su sistema y su configuración, por lo que, desafortunadamente, no será posible dar instrucciones universales. En Ubuntu, intente esto: copie - simplemente seleccione con el mouse, pegue - el botón central del mouse. Si no funciona, o si tienes un sistema diferente, busca en Internet o pregunta a amigos más experimentados.

Claves y opciones

Al explorar el historial de comandos, ya descubrió que el comando ls tiene al menos dos opciones. Si lo llamas así, genera una lista simple:

Akira@latitude-e7240: ~/shell-survival-quide> ls Makefile shell-first-steps.md shell-first-steps.pdf shell-survival-quide.md shell-survival-quide.pdf
Si agrega el modificador -l, se muestra información detallada para cada archivo:

Akira@latitude-e7240: ~/shell-survival-quide> ls -l total 332 -rw-rw-r-- 1 akira akira 198 13 de febrero 11:48 Makefile -rw-rw-r-- 1 akira akira 15107 febrero 14 22:26 shell-first-steps.md -rw-rw-r-- 1 akira akira 146226 13 de febrero 11:49 shell-first-steps.pdf -rw-rw-r-- 1 akira akira 16626 13 de febrero 11 :45 shell-survival-quide.md -rw-rw-r-- 1 akira akira 146203 13 de febrero 11:35 shell-survival-quide.pdf
esto es muy situación típica: si se agregan modificadores especiales (teclas, opciones, parámetros) a la llamada del comando, el comportamiento del comando cambia. Compare: árbol / y árbol -d / , nombre de host y nombre de host -f .

Además, los comandos pueden tomar nombres de archivos, nombres de directorios o simplemente cadenas de texto. Intentar:

Ls -ld /home ls -l /home grep root /etc/passwd

hombre

man: ayuda con los comandos y programas disponibles en su máquina, así como con las llamadas al sistema y la biblioteca estándar C.

Pruebe: man grep, man atoi, man chdir, man man.

El desplazamiento hacia adelante y hacia atrás se realiza con los botones “arriba”, “abajo”, “RePág”, “AvPág”, y salir de la vista de ayuda se realiza con el botón q. Buscar texto específico en el artículo de ayuda: presione / (barra diagonal), ingrese el texto para buscar, presione Entrar. Pasar a las siguientes apariciones - tecla n.

Todos los artículos de ayuda están divididos en categorías. Lo más importante:

  • 1 - programas ejecutables y comandos de shell (wc, ls, pwd, etc.);
  • 2 - llamadas al sistema (fork, dup2, etc.)
  • 3 - funciones de biblioteca (printf, scanf, cos, exec).
Es necesario indicar de qué categoría debe mostrarse el certificado en casos de coincidencia de nombres. Por ejemplo, man 3 printf describe una función de la biblioteca estándar de C y man 1 printf describe un programa de consola con el mismo nombre.

Puede ver una lista de todos los artículos de ayuda disponibles en su máquina usando el comando man -k. (el punto también es parte de la komada).

menos

Cuando estás en una pequeña ventana de terminal necesitas ver muy texto largo(el contenido de algún archivo, un hombre largo, etc.), utilizan programas especiales de "buscapersonas" (de la palabra página, es decir, volteadores de páginas). El desplazador más popular es el que le proporciona desplazamiento cuando lee páginas de manual.

Pruebe y compare el comportamiento:

gato /etc/bash.bashrc gato /etc/bash.bashrc |menos

Puede transferir el archivo al buscapersonas directamente en los parámetros:

Menos /etc/bash.bashrc

Desplazarse hacia arriba y hacia abajo - botones "arriba", "abajo", "Re Pág", "Av Pág", salir - botón q. Busque un texto específico: presione / (barra diagonal), ingrese el texto a buscar, presione Entrar. Pasar a las siguientes apariciones - tecla n. (¿Reconoces las instrucciones sobre el hombre? No es de extrañar, también se usa less para mostrar ayuda.)

Derechos

Cualquier archivo o directorio está asociado con un conjunto de “derechos”: el derecho a leer el archivo, el derecho a escribir en el archivo, el derecho a ejecutar el archivo. Todos los usuarios se dividen en tres categorías: propietario del archivo, grupo de propietarios del archivo y todos los demás usuarios.

Puede ver los permisos de archivos usando ls -l. Por ejemplo:

> ls -l Makefile -rw-r--r-- 1 estudiantes de Akira 198 13 de febrero 11:48 Makefile
Este resultado significa que el propietario (akira) puede leer y escribir el archivo, el grupo (estudiantes) solo puede leer y todos los demás usuarios también solo pueden leer.

Si recibe un mensaje de permiso denegado mientras trabaja, significa que no tiene permisos suficientes para el objeto con el que desea trabajar.

Lea más en man chmod.

STDIN, STDOUT, transportadores (tuberías)

Hay 3 flujos de datos estándar asociados con cada programa en ejecución: flujo de datos de entrada STDIN, flujo de datos de salida STDOUT, flujo de salida de error STDERR.

Ejecute el programa wc, ingrese el texto Buenos días hoy, presione Enter, ingrese el texto buenos días, presione Enter, presione Ctrl+d. El programa wc mostrará estadísticas sobre la cantidad de letras, palabras y líneas en su texto y finalizará:

> wc buen día hoy buen día 2 5 24
En este caso, proporcionó un texto de dos líneas al STDIN del programa y recibió tres números en STDOUT.

Ahora ejecute el comando head -n3 /etc/passwd, debería verse así:

> head -n3 /etc/passwd root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x: 2:2:bin:/bin:/usr/sbin/nologin
En este caso, el programa principal no leyó nada de STDIN, sino que escribió tres líneas en STDOUT.

Puedes imaginarlo de esta manera: el programa es una tubería por la que fluye STDIN y sale STDOUT.

La propiedad más importante La línea de comando de Unix permite que los programas "canalizados" se puedan conectar entre sí: la salida (STDOUT) de un programa se puede transferir como datos de entrada (STDIN) a otro programa.

Esta construcción de programas conectados se llama tubería en inglés o transportador o tubería en ruso.

La combinación de programas en una canalización se realiza con el símbolo | (barra vertical)

Ejecute el comando head -n3 /etc/passwd |wc, se verá así:

> cabeza -n3 /etc/contraseña |wc 3 3 117
Lo que sucedió es que el programa principal envió tres líneas de texto a STDOUT, que inmediatamente fue a la entrada del programa wc, que a su vez contó el número de caracteres, palabras y líneas en el texto resultante.

Puede combinar tantos programas como desee en una canalización. Por ejemplo, puede agregar otro programa wc al canal anterior, que contará cuántas palabras y letras había en la salida del primer wc:

> cabeza -n3 /etc/contraseña |wc |wc 1 3 24

Crear pipelines (tuberías) es una tarea muy común cuando se trabaja en la línea de comando. Para ver un ejemplo de cómo se hace esto en la práctica, lea la sección "Creación de un canal de una sola línea".

redirección de E/S

La salida (STDOUT) de un programa no sólo se puede transferir a otro programa a través de una canalización, sino que también se puede escribir simplemente en un archivo. Esta redirección se realiza usando > (signo mayor que):

Fecha > /tmp/today.txt
Como resultado de ejecutar este comando, el archivo /tmp/today.txt aparecerá en el disco. Ver su contenido usando cat /tmp/today.txt

Si ya existía un archivo con el mismo nombre, se destruirá su contenido anterior. Si el archivo no existía, se creará. El directorio en el que se crea el archivo debe existir antes de ejecutar el comando.

Si no desea sobrescribir un archivo, sino agregar salida al final, use >> :

Fecha >> /tmp/hoy.txt
Compruebe lo que ahora está escrito en el archivo.

Además, puedes pasar cualquier archivo al programa en lugar de STDIN. Intentar:

WC

Qué hacer cuando algo no está claro

Si encuentra un comportamiento del sistema que no comprende o desea lograr un resultado determinado, pero no sabe cómo, le aconsejo que proceda en el siguiente orden (por cierto, esto se aplica no solo a los shells):
  • Lo más claramente posible, formule la pregunta o tarea: no hay nada más difícil que resolver "algo que no sé qué";
  • recuerde si ya ha encontrado el mismo problema o uno similar; en este caso, vale la pena probar la solución que funcionó la última vez;
  • lea las páginas de manual correspondientes (si comprende qué páginas de manual son adecuadas en su caso); tal vez encuentre ejemplos adecuados del uso de comandos, las opciones necesarias o enlaces a otros comandos;
  • Piensa: ¿es posible cambiar un poco la tarea? - tal vez, cambiando ligeramente las condiciones, obtenga un problema que ya sabe cómo resolver;
  • haga su pregunta claramente formulada en un motor de búsqueda; tal vez la respuesta se pueda encontrar en Stack Overflow u otros sitios;
Si nada de lo anterior ayuda, busque el consejo de un profesor, un colega experimentado o un amigo. Y no tenga miedo de hacer preguntas "estúpidas": no es una pena no saberlo, es una pena no preguntar.

Si resuelves un problema difícil (por tu cuenta, con la ayuda de Internet u otras personas), escribe tu solución en caso de que a ti o a tus amigos les vuelva a surgir el mismo problema. Puedes grabarlo en un simple archivo de texto, en Evernote, o publicarlo en las redes sociales.

Métodos de trabajo

Copiar y pegar- de páginas de manual, de artículos sobre StackOverflow, etc. La línea de comando consta de texto, aproveche esto: copie y use comandos de ejemplo, anote los hallazgos exitosos como recuerdo, publíquelos en Twitter y blogs.

Extraiga el comando anterior del historial, agregue otro comando a la canalización, ejecute, repita.Centímetro. Consulte también la sección "Creación de un canal de una sola línea".

Comandos básicos

  • cambiar a otro directorio: cd ;
  • ver el contenido de los archivos: gato, menos, cabeza, cola;
  • manipulación de archivos: cp, mv, rm;
  • ver el contenido del directorio: ls , ls -l , ls -lS ;
  • estructura del directorio: árbol, árbol -d (el directorio se puede pasar como parámetro);
  • buscar archivos: buscar . -nombre ... ;

Analítica

  • baño, baño -l;
  • ordenar -k: ordenar por el campo especificado;
  • sort -n - clasificación numérica;
  • diff - comparación de archivos;
  • grep, grep -v, grep -w, grep "\ " , grep -E - buscar texto;
  • uniq, uniq -c - unicización de cadenas;
  • awk - en la opción awk "(print $1)", para dejar solo el primer campo de cada línea, $1 se puede cambiar a $2, $3, etc.;

Diagnóstico del sistema

  • ps axuww: información sobre los procesos (programas en ejecución) que se ejecutan en la máquina;
  • arriba: visualización interactiva de los procesos que consumen más recursos;
  • df: espacio libre y usado en disco;
  • du - tamaño total de los archivos en el directorio (recursivamente con subdirectorios);
  • strace, ktrace: qué sistema llama al proceso;
  • lsof: qué archivos utiliza el proceso;
  • netstat -na, netstat -nap: qué puertos y sockets están abiertos en el sistema.

Es posible que no tenga algunos programas; es necesario instalarlos adicionalmente. Además, algunas opciones de estos programas están disponibles sólo para usuarios privilegiados (root).

Ejecución masiva y semiautomática

Omita esta sección al principio; necesitará estos comandos y construcciones cuando llegue a las secuencias de comandos de shell simples.
  • prueba - condiciones de verificación;
  • while lectura en bucle línea por línea STDIN;
  • xargs: sustitución de cadenas de STDIN en parámetros del programa especificado;
  • seq - generación de secuencias de números naturales;
  • () - combina la salida de varios comandos;
  • ; - hacer una cosa tras otra;
  • &&: se ejecuta si el primer comando se completa correctamente;
  • || - ejecutar si falla el primer comando;
  • tee: duplica la salida del programa en STDOUT y en un archivo en el disco.

Misceláneas

  • fecha - fecha actual;
  • curl: descarga un documento desde la URL especificada y escribe el resultado en STDOUT;
  • toque - actualizar la fecha de modificación del archivo;
  • matar: envía una señal al proceso;
  • verdadero: no hace nada, devuelve verdadero, útil para organizar bucles eternos;
  • sudo: ejecuta el comando como root "a.

Creando un canal de una sola línea

Veamos un ejemplo de una tarea real: necesitamos eliminar todos los procesos del servidor de tareas 6 que se ejecutan como el usuario actual.

Paso 1.
Comprenda qué programa produce aproximadamente los datos necesarios, aunque no en su forma pura. Para nuestra tarea, vale la pena obtener una lista de todos los procesos del sistema: PD axuww. Lanzamiento.

Paso 2.
Mire los datos recibidos con sus ojos, cree un filtro que elimine algunos de los datos innecesarios. Suele ser grep o grep -v . Utilice la tecla "Arriba" para extraer el comando anterior del historial, asignarle un filtro inventado y ejecutarlo.

Ps axuww |grep `whoami`
- solo procesos del usuario actual.

Paso 3.
Repita el paso 2 hasta que obtenga los datos limpios que necesita.

"
- todos los procesos con el nombre requerido (más, quizás, algunos adicionales como vim task-6-server.c, etc.),

Ps axuww |grep `whoami` | grep "\ " | grep -v vim ps axuww |grep `whoami` | grep "\ " | grep -v vim |grep -v menos
- solo procesos con el nombre requerido

Ps axuww |grep `whoami` | grep "\ " | grep -v vim |grep -v less |awk "(imprimir $2)"

Pids de los procesos requeridos, paso 3 completado

Paso 4.
Aplicar un manipulador final adecuado. Usando la tecla "Arriba", sacamos el comando anterior del historial y agregamos el procesamiento que completará la solución al problema:

  • |wc -l para contar el número de procesos;
  • >pids para escribir pids en un archivo;
  • |xargs kill -9 procesos de eliminación.

Tareas de entrenamiento

¿Quieres practicar nuevas habilidades? Pruebe las siguientes tareas:
  • obtenga una lista de todos los archivos y directorios en su directorio de inicio;
  • obtener una lista de todos los artículos man de la categoría 2 (llamadas al sistema);
  • cuente cuántas veces aparece la palabra grep en la página de manual del programa grep;
  • cuente cuántos procesos se están ejecutando actualmente como root;
  • encontrar qué comando aparece en el número máximo de categorías de ayuda (hombre);
  • cuente cuántas veces aparece la palabra var en la página ya.ru.
Sugerencia: necesitará find , grep -o , awk "(print $1)" , expresiones regulares en grep , curl -s .

¿Qué estudiar a continuación?

Si te empieza a gustar la línea de comandos, no pares, sigue mejorando tus habilidades.

Aquí hay algunos programas que definitivamente te serán útiles si vives en la línea de comando:

  • encontrar con opciones complejas
  • a propósito
  • localizar
  • Telnet
  • netcat
  • tcpdump
  • sincronización
  • pantalla
  • zgrep, zless
  • visudo
  • crontab-e
  • enviar correo
Además, con el tiempo conviene dominar algún tipo de lenguaje de scripting, como Perl o Python, o incluso ambos.

¿Quién necesita esto?

¿Vale la pena aprender la línea de comandos y los scripts de shell hoy? Definitivamente vale la pena. Daré sólo algunos ejemplos de los requisitos de Facebook para los candidatos que quieran conseguir un trabajo en FB.

Cualquier sistema operativo universal tiene que jugar mucho con el usuario y sus propias tareas. Sólo una pequeña parte de esta actividad puede programarse de una vez por todas en el kernel. La mayor parte de la lógica para gestionar las tareas y el sistema en sí debe estar disponible para el administrador en forma de proyecto; de lo contrario, simplemente no podrá comprender lo que está sucediendo en el sistema y mucho menos cambiarlo. Vale la pena echar un vistazo más de cerca a la herramienta utilizada en UNIX para configurar el algoritmo para muchas partes del sistema: el intérprete de comandos, caparazón . Resulta que el shell funciona bien no sólo en el diálogo con el usuario, sino también en cómo intérprete de guión, y como medios para organizar la interacción entre tareas en el sistema.

Comencemos con el hecho de que el caparazón está completo. lenguaje de programación, y, como muchos intérpretes, de un nivel bastante alto. Si la tarea es única (no hay requisitos de velocidad, compatibilidad y portabilidad) y bastante abstracta (no hay conexión a una estructura de datos compleja específica), lo más probable es que se pueda resolver. escribiendo un script de comando- programa de shell.

Por otro lado, uno no puede limitarse a la completitud algorítmica al resolver problemas en un sistema. Por ejemplo, la máquina de Turing [9] es extremadamente simple y algorítmicamente completa, pero a pocos se les ocurriría organizar un diálogo con el usuario o controlar el propio sistema operativo basándose en su modelo. Aquí conviene recordar que el shell también es un ejecutor de comandos: se comunica fácilmente con UNIX y utilidades. Esto significa que al complementarlo con un mecanismo para la interacción controlada de comandos con el sistema y entre sí, obtendremos un buen integrador (o shell, que, de hecho, es la traducción de la palabra caparazón).

La mejor parte es que dicho shell programable no irá mucho más allá del alcance de Y: si, como legado de la encarnación interactiva del shell, podemos recurrir fácilmente a la solución de la subtarea para cualquier Utilidad UNIX, no hay absolutamente ninguna necesidad de duplicarla en el lenguaje, y allí solo quedarán abstracciones algorítmicas y de coordinación.

Guión

Antes de considerar las capacidades del caparazón desde dos ángulos, resolvamos esta dificultad. Digamos que escribimos un programa en el lenguaje de algún intérprete, por ejemplo /bin/sh, y lo escribimos en un archivo determinado, por ejemplo /home/george/myscript (si /home/george es el directorio actual, puede usar una ruta más corta: myscript). ¿Cómo puedo ejecutar este script ahora? De man sh sabemos que para hacer esto podemos ejecutar intérprete de comandos con el parámetro - nombre de archivo:

$ cat myscript echo "¡Hola, George!" $ /bin/sh myscript ¡Hola, George!

¿Es posible prescindir del nombre del programa que interpreta el guión? En términos generales, no: UNIX tiene muchos intérpretes diferentes con diferentes sintaxis, por ejemplo el procesador de textos. awk, transmisión editor de texto sed, universal lenguajes de programación Python y Perl y mucho más. Todos estos idiomas tienen la capacidad de insertar comentarios de línea en el texto del script, que comienzan con el carácter "#" y terminan al final de la línea. Por lo tanto, si un guión comienza con los caracteres "#!", cualquiera de estos intérpretes ignorará toda la primera línea como comentario. El sistema, al ver "#!" al principio del archivo, entiende que se trata de un script. Desde el tercer carácter hasta el final de la línea, lee el nombre del programa al que envía este archivo para su ejecución. Esto significa que si la primera línea en /home/george/myscript es #!/bin/sh , puedes convertirla en ejecutable de forma segura (establece el bit de uso) y ejecutarla:

$ chmod +x myscript $ cat myscript #!/bin/sh echo "¡Hola, $1!" $ ./myscript George ¡Hola, George!

Estrictamente hablando, después de "#!" puede ser cualquier cosa, por ejemplo el nombre del programa que escribimos con algunos parámetros requeridos; UNIX lo iniciará y se lo pasará como opciones de línea de comando parámetros requeridos (si los hay), luego el nombre del script y todo lo que viene después (en nuestro ejemplo, George). Si después de "#!" habrá un archivo inexistente, el sistema emitirá mensaje de error:

$ cat myscript #!/bad/sh echo "¡Hola, $1!" $ ./myscript ./myscript: no encontrado

Tenga en cuenta que este mensaje supuestamente implica que no se encontró el archivo de script en sí. Si no se conocen los antecedentes del fenómeno, la situación parece sospechosa. El hecho es que al ejecutar cualquier programa, UNIX Siempre le pasa un parámetro (que tiene índice 0): el nombre de este programa. Pero si se ejecuta el script, el controlador recibirá como parámetro nulo no su propio nombre, sino el nombre del script. Y cuando el sistema no encuentre este controlador, se mencionará con un nuevo nombre en el mensaje de error.

Nidos de conchas

Y una nota más importante. Al principio solo había uno en UNIX intérprete de comandos, escrito por Stephen Bourne, y simplemente se llamaba “shell” (es decir, shell, y el nombre de la utilidad es sh para abreviar). Era un pequeño programa muy simple, funcionaba perfectamente como integrador de sistemas, pero en todos los demás aspectos era bastante débil. Y entonces a los creadores de 3BSD se les ocurrió que necesitaban un sistema completamente nuevo. intérprete de comandos, más conveniente cuando se trabaja en la línea de comando, con nuevas capacidades de programación y una nueva sintaxis cercana al lenguaje C, que ya es familiar para cualquier programador de UNIX. El shell resultante se llamó C shell (por la sintaxis del comando; el nombre de la utilidad es csh), era mucho más poderoso que el anterior, incluía trabajar con el historial, completar nombres de archivos, gestión del trabajo; Aparecieron matrices y mucho más.




Arriba