Tutorial de la Terminal de Linux (Parte II)
Tutorial de la Terminal de Linux
Esta es la segunda parte de la charla sobre la terminal de linux, dada por Gustavo Castellanos y German Robayo, Coordinadores de Información y Tecnología del Centro de Estudiantes de Ingeniería de la Computación 2017-2018 de la Universidad Simón Bolívar.
Resumen de la Primera Parte
En este artículo escrito por mi companero @gustavoaca1997 se da un resumen de la primera parte de la charla sobre la terminal de Linux dictada a los estudiantes de la Universidad Simón Bolivar (USB). En éste se encuentran los siguientes tópicos:
- Flujos estándares.
stdout
,stdin
,stderr
. - Comandos basicos para manipulacion de ficheros:
ls
cd
man
el más importante de todospwd
mkdir
rm
cp
mv
- Direcciones de archivos absolutas y relativas.
Qué hablaremos
En este artículo hablaremos sobre lo siguiente:
- Control de flujo.
- Comandos intermedios.
- Procesos.
- Condicionales.
Control de flujo
Recordemos los tres flujos estándares: stdout
, stdin
y stderr
. Habíamos mencionado que Linux trata a estos como "ficheros". ¿Cómo manejamos el contenido de estos ficheros? La terminal provee operadores para ello.
>
¿Cómo se llama? Yo le digo pollito, sin razón alguna.
¿Cómo se usa?
$ pwd
/home/user/charla/
$ ls
a charla1 charla2 a.cpp b.c sample.py
$ echo "Todo bien?" > nuevoArchivo.txt
$ ls
a charla1 charla2 a.cpp b.c sample.py nuevoArchivo.txt
¿Qué hace? Transfiere el stdout
del programa del lado izquierdo y lo guarda en el archivo que se coloque en la derecha. NOTA: Reemplaza el contenido del archivo.
$ cat nuevoArchivo.txt
Todo bien?
<
¿Cómo se llama? Yo le digo menor que.
¿Cómo se usa? Tenemos un sencillo script de python que lee vía stdin
y luego imprime lo leído en mayúsculas.
$ ls
a charla1 charla2 a.cpp b.c sample.py nuevoArchivo.txt
$ cat sample.py
x = input()
print(x.upper())
$ cat nuevoArchivo.txt
Todo bien?
$ python3 sample.py < nuevoArchivo.txt
TODO BIEN?
¿Qué hace? Convierte el contenido del archivo de la derecha en stdin
para el comando de la izquierda. Permite hacer combinaciones de comandos muy elegantes e interesantes.
$ python3 sample.py < nuevoArchivo.txt > out.txt
$ cat out.txt
TODO BIEN?
Aqui hicimos uso del >
para capturar el stdout
del comando y guardarlo en out.txt.
>>
¿Cómo se llama? Yo le digo doble pollito.
¿Cómo se usa? Igual que el >
¿Qué hace? Funciona igual que el >
, pero la diferencia es que este anade contenido al final, en vez de sobreescribirlo.
<<
¿Cómo se llama? Yo le digo doble menor igual.
¿Cómo se usa? Igual que el <
¿Qué hace? Este es interesante. Permite recibir el input como un here-document
¿Qué significa esto? Mas facil explicarlo con un ejemplo:
$ cat << EOF > texto.txt
Esto esta escrito por el teclado
Puedo seguir escribiendo hasta que escriba EOF
eof no, EOF
EOF con mas cosas no, solo EOF
EOF
# output
Esto esta escrito por el teclado
Puedo seguir escribiendo hasta que escriba EOF
eof no, EOF
EOF con mas cosas no, solo EOF
¿Qué paso exactamente? Cuando usamos <<
, el intérprete leerá nuestro input (stdin
) hasta que se escriba EOF
(el lado izquierdo). Nótese que no es necesario restringirse a EOF
, puedo usar cualquier cosa.
$ cat << EMPANADAS > texto.txt
Muchas empanadas no le hacen daño a nadie.
texto
texto
empanadas
EMPANADAS DE CAZÓN
EMPANADAS
# output
Muchas empanadas no le hacen daño a nadie.
texto
texto
empanadas
EMPANADAS DE CAZÓN
Hasta el momento hemos visto operadores que trabajan con archivos. ¿Cómo manejo los flujos generados por los programas?
|
¿Cómo se llama? Yo le digo pipe, como una tubería, ya verán por que.
¿Cómo se usa? Seguimos con nuestro sencillo script de python.
$ echo 'empanadas' | python3 sample.py
EMPANADAS
¿Qué hace? Transfiere el stdout
del comando de la izquierda y lo transforma como stdin
del de la derecha. Funciona como una tuberia, por eso el nombre. Esto permite generar combinaciones de comandos muy interesantes (ejemplos más abajo).
Comandos intermedios
Algo en común que tienen todos los comandos ya expuestos (a excepción de cat
y otros mas), es que todo su input es pasado mediante argumentos, es decir, si hacemos:
$ ls
a charla1 charla2 a.cpp b.c sample.py nuevoArchivo.txt
$ ls charla1
# cosas random, o nada posiblemente.
$ echo charla1
charla1
$ echo charla1 | ls
a charla1 charla2 a.cpp b.c sample.py nuevoArchivo.txt
¿Qué sucedió exactamente? |
Redirige stdout
en stdin
, pero ls
no recibe argumentos via stdin
, lo tienes que colocar a mano. A continuación, veremos muchos comandos que si aceptan stdin
como argumentos y otros que te permiten hacer que comandos como ls
puedan recibir stdin
.
tail
¿Qué hace? Recibe datos tanto por argumentos como por stdin
. En ambos casos, muestra las últimas 10 líneas de los datos.
# texto20lineas.txt tiene los numeros del 1 al 20 uno en cada linea.
$ cat texto20lineas.txt
1
2
3
4
5
...
19
20
$ cat texto20lineas.txt | tail
11
12
13
14
15
16
17
18
19
20
$ tail texto20lineas.txt
11
12
13
14
15
16
17
18
19
20
Se le puede pasar como opcion -n
usando como n
cualquier numero, mostrará las últimas n
líneas del archivo.
head
Hace exactamente lo mismo que tail
, pero muestra las primeras 10 líneas, no las últimas.
less
Para explicar este archivo vamos a entrar en la siguiente situación. Supongamos que tenemos un archivo que tiene 1000 líneas aproximadamente (un código largo, por ejemplo). Si ejecutamos cat archivolargo.txt
no podremos leerlo facílmente, pues nos mostrará todo el output. Si en vez ejecutamos less archivolargo.txt
nos mostrará una especie de interfaz, en la que podremos ver nuestro archivo poco a poco subiendo con k
y bajando con j
. Podemos buscar tecleando /patron_de_búsqueda
y bajar hasta el final presionando G
. less
tambien lee via stdin
.
grep
Este es de mis comandos favoritos y mas útiles. Es muy poderoso, aunque muy poco comprendido. grep
busca patrones en los archivos o en el stdin
que le mandes e imprime, al stdin
, las líneas que hagan match. Veamos un ejemplo:
$ cat texto.txt
El terminal es interesante
¿Cómo te llamas?
Tu nombre suena interesante...
# Cada 'interesante', dependiendo de la terminal, estará resaltado de algun
# color reflejando match.
$ grep interesante texto.txt
El terminal es interesante
Tu nombre suena interesante...
Los patrones que puedes usar son expresiones regulares, algo de lo que hablaré en un próximo artículo.
Le podemos pasar más opciones, como por ejemplo:
-v
: Invierte el sentido de matching.-E
: Permite el uso de expresiones regulares extendidas
Recuerda que si quieres ver mas información sobre este y cualquier otro comando, puedes usar el manual, man
.
wc
Este comando, aunque tiene un nombre raro (sí, sé lo qué estas pensando), te da la siguiente información sobre los argumentos que le pases o el stdin
que recibe:
- Número de caracteres
\n
, esto indica cuantas líneas tiene el archivo. - Número de bytes. En la computadora, cada caracter ocupa un byte en memoria (si no son unicode), así que el número de bytes de un archivo es equivalente al número de caracteres que posee.
- Número de palabras.
Ejemplo:
$ cat texto.txt
El terminal es interesante
¿Cómo te llamas?
Tu nombre suena interesante...
$ wc texto.txt
3 11 77
El primer número es el numero de líneas, el segundo el número de palabras y el tercero de bytes.
chmod
Antes de explicar qué hace este comando, voy a dar una muy breve explicación sobre los modos en los ficheros de linux.
Existen 3 tipos de individuos en un sistema operativo linux:
- Usuario: Con esto linux se refiere a ti, el que esta haciendo uso del terminal y el que tiene cuenta en la maquina.
- Grupo: En linux, podemos organizar los usuarios en grupos lo que nos permite poder administrar la información de una manera eficiente.
- Otros: Son el conjunto de usuarios menos tu.
Ahora, sabiendo esta información, existen 3 permisos que se le pueden otorgar a los archivos sobre cierto tipo de individuos.
- Escritura: Va directamente asociado a quienes pueden modificar el archivo, sea sobreescribiéndolo,
modificando o añadiendo líneas. - Lectura: ¿Quienes pueden leer el archivo? Los permisos de lectura son para eso, restringir que personas pueden leerlo.
- Ejecución: ¿Se puede ejecutar? ¿Quienes pueden ejecutarlo?
Ahora, sabiendo esto, veamos qué hace chmod y cómo usarlo.
$ ls
a a.cpp b c guardado hola.txt sample.py sample.txt test test2.py
test2.txt test.py test.txt
$ ls -l # Investigar que hace -l, man ls
total 64
-rwxrwxr-x 1 username username 9168 ene 18 14:24 a
-rw-rw-r-- 1 username username 112 ene 18 14:24 a.cpp
-rwxrwxr-x 1 username username 9168 ene 18 14:24 b
-rw-rw-r-- 1 username username 0 ene 18 14:24 c
-rw-rw-r-- 1 username username 16 ene 18 14:44 guardado
-rw-rw-r-- 1 username username 5 ene 18 14:54 hola.txt
-rw-rw-r-- 1 username username 22 ene 18 13:51 sample.py
-rw-rw-r-- 1 username username 13 ene 18 14:34 sample.txt
drwxrwxr-x 2 username username 4096 ene 18 14:26 test
-rw-rw-r-- 1 username username 73 ene 18 15:08 test2.py
-rw-rw-r-- 1 username username 26 ene 18 15:12 test2.txt
-rw-rw-r-- 1 username username 30 ene 18 14:56 test.py
-rw-rw-r-- 1 username username 18 ene 18 14:57 test.txt
Observen la primera columna, tiene un formato raro. Consiste de una palabra de 10 caracteres donde el primer caractér indica si es un directorio, y los otros nueve son tripletas de r
,w
y x
. La primera tripleta es respecto al usuario,
la segunda respecto al grupo y la tercera a los otros. La r
indica permisos de lectura, la w
de escritura y la x
de ejecución. Por ejemplo, el archivo a.cpp
tiene permisos de lectura para todo el mundo pero nada mas pueden modificarlos el usuario actual (que no necesariamente es username
) y el grupo username
(el grupo está en la tercera columna).
Supongamos que por alguna razón necesito agregar permisos de ejecución para todos los usuarios en el archivo a.cpp
. Puedo ejecutar:
$ chmod +x a.cpp
$ ls -l a.cpp
-rwxrwxr-x 1 username username 112 ene 18 14:24 a.cpp
# ^ ^ ^ Se añadieron los permisos para todos.
Ahora queremos quitarselos
$ chmod -x a.cpp
$ ls -l a.cpp
-rw-rw-r-- 1 username username 112 ene 18 14:24 a.cpp
# ^ ^ ^ Se eliminaron los permisos para todos.
Solo quiero que el usuario actual tenga permisos de ejecución
# la 'u' se refiere al usuario actual, si el usuario que lo ejecuta no es el dueño
# del archivo lanzará un error.
$ chmod u+x a.cpp
$ ls -l a.cpp
-rwxrw-r-- 1 username username 112 ene 18 14:24 a.cpp
# ^ Se añadio el permiso de ejecución los permisos para todos.
Solo quiero que los demás tengan solamente permiso de escritura
# la 'o' se refiere a los otros usuarios
$ chmod o=w a.cpp
$ ls -l a.cpp
-rwxrw--w- 1 username username 112 ene 18 14:24 a.cpp
# ^ SOLAMENTE permisos de escritura
Si quiero que quiero que el grupo tenga solo permisos de lectura, añadir al usuario de ejecución y quitarle todos los permisos a los otros usuarios
# La 'g' se refiere al grupo del archivo
$ chmod g=r,u+x,o-rwx a.cpp
$ ls -l a.cpp
-rwxr----- 1 username username 112 ene 18 14:24 a.cpp*
Así que, aunque no lo mencioné, chmod
sirve para modificar permisos de ficheros.
xargs
Este permite que comandos que no reciben nada via stdin como ls
puedan hacerlo. xargs
recibe via stdin
y se lo coloca como argumentos a su argumento.
Ejemplo:
$ ls -1 *.txt # -1 te coloca todo en una sola columna, * es el wildcard.
hola.txt
sample.txt
test2.txt
test.txt
$ ls -1 *.txt | rm # Arroja error por que rm recibe argumentos, no `stdin`
rm: falta un operando
Pruebe 'rm --help' para más información.
$ ls -1 *.txt | xargs rm
$ ls -1 *.txt # Arroja error por que no hay archivos .txt
ls: no se puede acceder a '*.txt': No existe el archivo o el directorio
Procesos
Hasta el momento hemos hecho abuso de la palabra programa cuando en realidad hay
que hacer una diferencia notoria:
- Un programa es un archivo que contiene instrucciones que leera y ejecutar el
computador. Ejemplo: Scripts de python, programas en C, C++, binarios. - Un proceso es cuando el sistema operativo le asigna recursos suficientes para
que se pueda llevar acabo la ejecución de un programa.
Sabiendo esto, podemos concluir que un comando seria un programa y su ejecución un proceso.
¿Para qué nos interesa esto? Linux es un sistema operativo multiprocesos. Nos permite ejecutar varios procesos a la vez. ¿Cómo vemos los procesos que se están ejecutando?
ps
Este comando lista los procesos que se estan ejecutando en la terminal actual con
cierta información sobre cada uno.
$ ps
PID TTY TIME CMD
2034 pts/0 00:00:00 bash
9310 pts/0 00:00:00 ps
Podemos observar 3 columnas. La primera es el PID, que significa Process ID, cada proceso tiene un número único que lo identifica. El TTY es la terminal de donde se esta ejecutando, pts/0
. La columna TIME indica la cantidad de tiempo que ha usado el cpu para la ejecución de ese comando. Dirán:
¿Porqué si el
bash
se lleva ejecutando desde que abrí la terminal dice 00:00:00?
Aquí viene el plotwist. Cuando ejecutas un comando, no mandas a ejecutarbash
, mandas a ejecutar dicho comando. Elbash
no interfiere en nada en la ejecución del comando.
La cuarta columna CMD indica el comando que se esta ejecutando en dicho proceso.
&
El ampersand en la línea de comandos tiene una función. Correr un proceso en segundo plano (background). Cuando ejecutamos un comando se ejecuta en primer plano (foreground) por defecto, lo que nos quita la posibilidad de ejecutar otro programa sino hasta que termine la ejecución de este. Si lo ejecutamos en segundo plano, podremos seguir usando la terminal sin ningún inconveniente.
Ejemplo:
$ comando_que_tarda_10_minutos
# Toca esperar 10 minutos hasta que termine la ejecución
# del programa
$ comando_que_tarda_10_minutos &
[1] 12313
$ # Tenemos disponibilidad de ejecutar cualquier otro programa.
El [1]
indica el jobID y el numero de al lado es el process ID.
Si ejecutamos ps
:
$ ps # EL TIME PUEDE SER DISTINTO
PID TTY TIME CMD
2034 pts/0 00:00:00 bash
9310 pts/0 00:00:00 ps
12313 pts/0 00:00:30 comando_que_tarda_10_minutos
Ahí esta nuestro proceso, siendo ejecutado hasta que termine solo o le manden una
señal.
kill
Permite mandar señales a procesos. Las señales que mas uso son: SIGKILL, SIGTERM.
Ejemplo:
$ ps
PID TTY TIME CMD
2034 pts/0 00:00:00 bash
9310 pts/0 00:00:00 ps
12313 pts/0 00:00:30 comando_que_tarda_10_minutos
$ kill -9 12313 # 9 es el codigo de la señal SIGKILL
$ # presiona enter
[1]+ Terminado (killed) comando_que_tarda_10_minutos
$ ps
PID TTY TIME CMD
2034 pts/0 00:00:00 bash
9310 pts/0 00:00:00 ps
Ejemplo de la vida real
Supongamos que estamos escribiendo código en sublime y se quedó congelado, no responde. Podemos ver TODOS los procesos haciendo:
$ ps -aux
... # monton de output
Demasiado output y nada útil a la vista. Usemos grep
$ ps -aux | grep subl
german 13084 11.5 1.2 988756 47788 ? Ssl 20:54 0:01 /opt/sublime_text/sublime_text
german 13096 30.5 0.9 78332 36500 ? Dl 20:54 0:02 /opt/sublime_text/plugin_host 13084
german 13107 0.0 0.0 16760 972 pts/0 S+ 20:54 0:00 grep --color=auto subl
3 procesos y uno es grep así que ese no puede ser. Ajuro deben ser los otros.
Matemoslos:
$ kill 13084 13107
Sublime cierra exitosamente.
Si llegaste hasta aquí
Quiero agradecerte a ti, querido lector por haber leído este tutorial que he escrito junto con mi compañero @gustavoaca1997. Espero que te haya gustado y que te sirva de ayuda. Mantente pendiente de futuros tutoriales sobre este tipo de cosas.
¡Hasta la proxima!
Congratulations @german1608! You received a personal award!
Click here to view your Board of Honor
Congratulations @german1608! You received a personal award!
You can view your badges on your Steem Board and compare to others on the Steem Ranking
Vote for @Steemitboard as a witness to get one more award and increased upvotes!