Saltar a contenido

Sistemas

Instalar Telnet en nuestro sistema

Telnet es un protocolo cuya función es interconectar dos dispositivos de redes cualesquiera para obtener una administración o gestión remota. Su publicación fue en el 1983 bajo el RFC854 (Request for Comments). Este utiliza el protocolo TCP (Transmission Control Protocol) o lo que es lo mismo, Protocolo de Control de Transmisión con la finalidad de no perder información cuando se tiene una sesión abierta a través de Telnet.

También se le ha atribuido algunos usos como enviar peticiones a servidores Web entre otras cosas.

NOTA: Tenemos que tener en cuenta, que Telnet debe tener el puerto 23 abierto para poder funcionar.

Instalación del cliente

A continuación veremos como instalar el cliente de Telnet tanto en Linux como en Windows.

Linux

Procederemos a instalarlo en las diferentes distribuciones populares:

Fedora

No más sencillo que:

# dnf install telnet

CentOS

Parecido a Fedora:

# yum install telnet-server

OpenSUSE Leap o Tumbleweed

Más fácil imposible:

$ sudo pacman -S telnet

Gentoo

Inconfundible:

$ sudo emerge -av telnet-bsd

Ubuntu, Debian, derivados

Sin dudarlo:

$ sudo apt-get install telnet

Código fuente

Procederemos a explicar cómo instalarlo mediante código fuente: 1. Descargamos el src desde el siguiente enlace. 2. Descomprimimos el archivo 3. Configuramos el prefix

```
./configure --prefix=/usr
```
  1. Compilamos

    make 5. Instalamos

    make install 6. Y ya podemos utilizarlo

Nota: Tenemos que acordarnos que si utilizamos otro PREFIX que no se encuentre recogido dentro de la variable PATH de algún fichero en /etc/profile.d/ o ~/.bash_profile no saldrá disponible a menos que ejecutes el comando telnet con ruta absoluta.

Windows

Telnet en Windows no lleva mucha complicación ya que en la mayoría de versiones es el mismo procedimiento a realizar.

  1. Nos dirigimos al Panel de control
  2. Activar características de Windows
  3. Marcar el checkbox Cliente Telnet
  4. Reiniciar y ya podemos acceder al cliente desde cmd.exe

[owl-carousel items=1 margin=10 loop=true autoplay=true autoplayHoverPause=true nav=true] [/owl-carousel]

Ejecutando Telnet

Abrimos un intérprete de comandos tanto en Linux bash, gnome-terminal... como en Windows cmd.exe o PowerShell y ejecutamos telnet: telnet

Conectándonos a un servidor

Para conectarnos basta con hacer:

telnet IP_SERVIDOR

Instalación de un servidor

En este punto instalaremos un servidor de Telnet tanto en Linux como en Windows.

Linux

Distribuciones

Fedora o CentOS

Tan fácil como:

# dnf install telnet-server
# systemctl start telnet.socket

Y ya podremos conectarnos, por ejemplo, desde localhost:

$ telnet 127.0.0.1

OpenSUSE Tumbleweed / Leap

Es un procedimiento un poco más elaborado que el de Fedora:

$ sudo zypper in telnet-server
$ sudo sed -ie 's/yes/no/g' /etc/xinet.d/telnet

Le decimos a xinetd(1) que incie telnet Nota: xinetd(1) es un servicio que administra las conexiones a determinados servicios utilizados por Internet como en este caso, Telnet.

Iniciando el servidor:

$ sudo systemctl start xinetd

Para probar el servidor, nos intentamos loguear con nuestra propia máquina (loopback):

$ telnet 127.0.0.1

Debian, Ubuntu y derivados

Si en OpenSUSE es xinetd(1), aquí la gente de Debian, Ubuntu y derivados hacen uso de inetd(1), que es el servicio previo a xinetd(1).

$ sudo apt-get install telnetd

Esto bastará para lanzar automáticamente el servicio:

$ telnet 127.0.0.1

Sin embargo, si queremos confirmar y verificar de que se iniciará telnet(1) al arranque del sistema con inetd(1) hay que verificar el archivo /etc/inetd.conf y fijarnos en la línea que nos dice:

telnet stream tcp nowait telnetd /usr/sbin/tcpd /usr/sbin/in.telnetd

Y añadirlo al arranque:

$ sudo systemctl enable inetd

Gentoo (systemd)

Para instalar el servidor de Telnet en Gentoo bastará con hacer los siguientes pasos:

$ sudo emerge -av telnet-bsd

Generamos este fichero en el directorio /etc/systemd/system/telnetd.socket

Description=Telnet Server Activation Socket
Documentation=man:telnetd(8)

[Socket]
ListenStream=23
Accept=true

[Install]
WantedBy=sockets.target

Posteriormente, creamos otro fichero en /etc/systemd/system/telnetd@.service

[Unit]
Description=Telnet Server
After=local-fs.target

[Service]
ExecStart=/usr/sbin/in.telnetd
StandardInput=socket

Lanzamos el servidor:

# systemctl start telnetd.socket

Probamos si funciona con:

$ telnet 127.0.0.1

Añadiendo telnetd(8) al arranque:

# systemctl enable telnetd.socket

Deshabilitándolo:

# systemctl disable telnetd.socket

Código fuente

Para instalarlo en una distribución Linux utilizando systemd como gestor de servicios, hay que acordarse en qué ruta hemos instalado telnetd. Una vez la tengamos, sólo tendremos que crear los ficheros que hemos añadido en el paso de Gentoo con el PREFIX correcto.

Creamos y añadimos la siguiente información /etc/systemd/system/telnetd.socket

Description=Telnet Server Activation Socket
Documentation=man:telnetd(8)

[Socket]
ListenStream=23
Accept=true

[Install]
WantedBy=sockets.target

Luego creamos el fichero /etc/systemd/system/telnetd@.service

[Unit]
Description=Telnet Server
After=local-fs.target

[Service]
ExecStart=/usr/sbin/in.telnetd
StandardInput=socket

Probemos si funciona con:

$ telnet 127.0.0.1

Windows

Para instalar el servidor de Telnet en Windows, los pasos generalmente son los mismos tanto para 7, 8 o 10.

  1. Nos dirigimos al Panel de control
  2. Activar características de Windows
  3. Marcar el checkbox Servidor Telnet
  4. Reiniciar
  5. Ejecutamos services.msc
  6. Buscamos el apartado servidor Telnet -> Clic derecho -> Propiedades
  7. Pinchar en Deshabilitado -> Manual -> Iniciar (Si queremos que inicie con el sistema lo pasamos a automático)

[owl-carousel items=1 margin=10 loop=true autoplay=true autoplayHoverPause=true nav=true] [/owl-carousel]

Referencias

  1. RFC854
  2. Microsoft's doc social network
  3. Google
  4. Gentoo

Mastering en Bash - Buscando archivos y directorios

¿A quién no le interesa encontrar a esta buscada ballena en medio de un océano tan grande? Pues a nosotros no la verdad, preferimos buscar otro tipo de cosas como archivos y directorios en nuestro sistema. Para ello haremos uso de los comandos find(1), locate(1), whois(1),whereis(1).

Diferencias

find(1) a diferencia de locate(1) es un comando que busca a tiempo real y tiene muchísimas funcionalidades añadidas como filtrar por nombre, tipo de ejecutable, fecha, hora.... e incluso, eliminar los ficheros que hemos querido encontrar, mientras que locate(1) trabaja junto con una base de datos generada por updatedb(8) reduciendo drásticamente la actualización puntera de la ubicación de los ficheros y directorios además de no tener la afinidad que posee find(1).

asciicast

Trabajando con find(1)

En este artículo vamos a guiarnos más por los ejemplos que por explicar la sintaxis o los parámetros de uno en uno.

Encontrar todos aquellos ficheros y directorios que se encuentren en el directorio /etc, y que aquellos directorios a los que no no podamos acceder a su contenido, no nos muestre el error de permisos.

find /etc 2>/dev/null 

Encontrar todos aquellos archivos en /var/ cuya extensión sea .log, y que por supuesto, no muestre aquellos directorios que requieran permisos para su acceso.

find /var -name "*.log" 2>/dev/null

Mostrar todos los directorios de nuestro /home sin contar los archivos

find ~ -type d

Encontrar archivos vacíos en nuestro /home y eliminarlos todos

find ~ -empty -type f -exec rm -rf {} \;

Encontrar ficheros con extensión .log y copiarlos en una carpeta dentro de nuestro home con permisos de superusuario

sudo find /var -name ".log" -exec cp {} /home/sincorchetes/LOGS \;

Buscando archivos cuya fecha de modificación sea de hace un minuto en nuestro /home

find ~ -cmin 1 

Ficheros que han sido accedidos hace 10 minutos

find ~ -amin 10

Visualizar archivos que contengan .log de extensión, contengan permisos 644

sudo find /var -name "*.log" -perm 644

Ver archivos que pesen igual o redondeando den 2GB en nuestro directorio

find ~ -size 2G

Buscar directorios que contengan nuestro nombre de usuario, con permisos 777.

find / -user sincorchetes -type d -perm 777

Mostrar todos los archivos o directorios simbólicos que se encuentren en el directorio /dev y mostrarlo como si ejcutásemos un ls(1)

sudo find /dev -type l -ls

Listando aquellos archivos de nuestro /home cuya extensión contenga "*.avi" y sean iguales o superiores a 1G

find ~ -name "*.avi" -a -size 1G

Suprimiendo los .rpm que encontremos que lleguen a 10 megas

sudo find /var/cache/rpm -name "*.rpm" -a -size 10M -exec rm -rf {} \;

Podemos seguir ejemplos del manpages de find(1) o imaginarnos lo que se nos ocurra que podamos hacer en un futuro, estos son solo pequeños ejemplos de lo que podemos hacer con esta fantástica utilidad.

Trabajando con locate(1)

Bien, como hemos dicho anteriormente, este comando hace uso de una base de datos que por lo general suele ubicarse en /var/lib/mlocate/mlocate.db, y su fichero de configuración suele encontrarse en /etc/updatedb.conf todo depende de la distribución que utilicemos.

También podemos hacer un indexado que es registrar todos los archivos y directorios que queramos y se almacenen por un cierto orden en la base de datos de locate, sin tener que hacer uso de superusuario o creando un daemon en el sistema.

Regenerando las bases de datos

Podemos hacer que nos indexe todo lo que contenga el sistema y que lo puedan ver tod@s l@s usuari@s.

sudo updatedb

O bien, podemos generar una base de datos para nosotr@s.

mkdir .locate
updatedb -l 0 -U /DIR -o .locate/db_file

-l 0: Permite entre otras cosas, crear el fichero de la base de datos utilizando nuestro usuario. -U /DIR: Directorio a idnexar -o nombre_fichero: El nombre que le pondremos a la db

Si queremos añadir más directorios, tendremos que ejecutar el comando modificando /DIR

Buscando archivos o directorios

Basta con ejecutar locate nombre_archivo/nombre_dir y el comando nos arrojará una salida completa con las coincidencias que encuentre en la db.

Sin embargo, si queremos ejecutar nuestro fichero, tendremos que especificárselo a locate(1)

locate nombre_directorio/nombre_archivo -d .locate/db_file

Visualizando estadísticas

Se pueden ver cuántos archivos y directorios tenemos actualmente registrados en cada db.

locate -S 

ó

locate -Sd .locate/db_file

El comando whereis(1)

Este comando nos viene de fábula cuando queremos encontrar algún binario, archivo fuente o incluso páginas de manual de man(1), para hacerlo, este lleva una búsqueda en aquellos directorios que se encuentren declarados en la variable $PATH y $MANPATH. Estas variables las podemos encontrar en /etc/profile o en ~/.bash_profile (en nuestro caso)

echo $PATH

Nuestra salida:

echo $PATH
/usr/lib/qtchooser:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/home/sincorchetes/.composer/vendor/bin:/home/sincorchetes/.local/bin:/home/sincorchetes/bin:/home/sincorchetes/.bin/scripts

Vamos a visualizar un par de ejemplos.

Buscando una página con la coincidencia cat(1)

whereis -m cat

Encontrando la ubicación del binario

whereis -b cat

Buscando la fuente de un kernel de Fedora 28

whereis -s 4.16.8-300.fc28.

Comando whatis(1)

Este comando nos permite buscar en las páginas de man(1) y nos devuelve una descripción del mismo en una sola línea, en caso de que encuentre varios resultados, mostrará ambos o más y su categoría dentro de man(1).

whatis cat

Salida:

cat (1p)             - concatenate and print files
cat (1)              - concatenate files and print on the standard output

Podemos especificar un directorio diferente para que busque en otras páginas de man(1) pues que no tengamos instaladas en el directorio raíz o no se encuentren registradas en ~/.bash_profile

whatis -M ~/.man/ cat

Entre otras cosas

Comando apropos(1)

Este comando es parecido al anterior, lo que utiliza directamente mandb(1), también permite utilizar otra ruta de directorio para los manpages...etc

apropos whatis

Salida:

whatis (1)           - display one-line manual page descriptions

Y con esto acabamos el artículo de hoy, esperemos que os haya gustado.

¡Un saludo!

Referencias

  • manpages
  • find(1)
  • locate(1)
  • updatedb(1)
  • whereis(1)
  • whatis(1)
  • apropos(1)

Mastering en Bash - Condicionales

En esta entrega comenzaremos a ver los condicionales de los que disponemos en Bash.

Off-Topic: Vamos a resumir los artículos y separarlos por subcontenidos para hacer más ágil su lectura, lo hemos aprendido el post anterior Mastering en Bash ~ Primero de Scripting, en el que hemos inyectado mucha cantidad de contenido de golpe a pesar de ser muy útil, puede parecer pesada su lectura.

¿Qué es un condicional?

Imaginémonos que vamos a comprar el pan y resulta de que o bien no hay, o bien sale más caro de lo que imaginamos, o bien no es el tipo que buscamos...etc, entonces tenemos que pensar ¿Qué hacer? y aquí entra en juego el uso de los condicionales.

Los condicionales son evaulaciones que aplicamos en determinados valores que obtenemos como resultado de una operación anterior, bloques de código que han sido ejecutados y que han devuelto alguna salida. Es decir, con el if regularemos el flujo de trabajo de nuestro sript, añadiendo diferentes situaciones para resultados diferentes.

If

If permite añadir una situación diferente que en caso de que no se cumpla la condición, continuará ejecutando el resto del código. Este se puede elaborar en dentro de un script (como haremos a partir de ahora), o bien se puede ejecutar en una sola línea de ejecución en Bash.

Creamos un script dónde añadiremos el siguiente bloque de código.

estado="Cerrado"
parque=$estado

if [ $parque == "Cerrado"]
then
    echo "Está cerrado"
fi

Si ejecutamos el código de arriba, nos devolverá un mensaje de que se encuentra cerrado. Sin embargo, si cambiamos "Cerrado" => "Abierto". La cosa cambia, ya que no producirá una salida.

estado="Cerrado"
parque=$estado

if [ $parque == "Cerrado"]
then
    echo "Está cerrado"
fi

¿Por qué sucede esto? Porque como la condición no se cumple, ya que caracter-caracter se va comprobando que sean correctos dentro de la condición, en cuanto sea alguno de ellos distinto, se prosigue con el resto del código sin hacer nada al respecto. Si queremos decirle que ejecute otra instrucción de código utilizaremos la sentencia else.

estado="Cerrado"
parque=$estado

if [ $parque == "Cerrado"]
then
    echo "Está cerrado"
else
    echo "Está abierto"
fi

Pero... ¿Y si queremos añadir más condiciones? Un parque puede estar abierto, cerrado, en obras entre otras cosas. Para eso tenemos la sentencia if-elif

estado="Abierto"
parque=$estado

if [ $parque == "Cerrado"]
then
    echo "Está cerrado"
elif [ $parque == "Abierto" ]
then
    echo "Está abierto"
fi

Más estados...

estado="Obras"
parque=$estado

if [ $parque == "Cerrado"]
then
    echo "Está cerrado"
elif [ $parque == "Abierto" ]
then
    echo "Está abierto"
elif [ $parque == "Obras" ]
then
    echo "Está en obras"

else
    echo "Consulte al ayuntamiento de su ciudad"
fi

Condicional en una simple linea

Se pueden escribir condicionales en una sola línea, acortando todo el bloque de código en una sola instrucción reduciendo el consumo de memoria y de procesamiento, pero aumentando la complejidad de lectura para el desarrollador.

if [ $parque == "Cerrado" ]; then  echo "Está cerrado" ; elif [ $parque == "Abierto" ]; then  echo "Está abierto" ; elif [ $parque == "Obras" ]; then echo "Está en obras" ; fi

¿Cómo evalúa if todo esto?

Los corchetes que incluimos como sintaxis del if, realmente esconden el comando test(1). Este comando básicamente compara valores, por ejemplo:

[ 2 -eq 0 ]

Si hacemos un echo $? para ver el resultado de la ejecución del comando, nos saldrá un 1 como señal de ARCHIVOALSE.

[ 0 -eq 0 ]

Al hacer un echo $? nos mostrará el 0, de verdadero.

Lo mismo da utilizar los corchetes como llamar directamente al comando.

test 0 -eq 0

Veremos el resultado de la ejecución del comando, recordemos 0 es éxito !=0 puede ser un error.

echo $?

Tabla de expresiones utilizadas

Las siguientes expresiones devuelven todas verdadero en su defecto en caso de que cumplan la condición. Para ver el resultado, hay que verificar la salida de la ejecución del comando con echo $?

Expresión en terminal Descripción
[ -a ARCHIVO ] ARCHIVO existe
[ -b ARCHIVO ] ARCHIVO existe y es un fichero especial de bloques
[ -c ARCHIVO ] ARCHIVO existe y es archivo especial de caracteres
[ -d ARCHIVO ] ARCHIVO existe y es un directorio
[ -e ARCHIVO ] ARCHIVO existe
[ -f ARCHIVO ] ARCHIVO existe y es un archivo regular
[ -g ARCHIVO ] ARCHIVO existe y tiene el SGID asignado
[ -h ARCHIVO ] ARCHIVO existe y es un enlace simbólico
[ -k ARCHIVO ] ARCHIVO existe y tiene asignado sticky bit
[ -p ARCHIVO ] ARCHIVO existe y está nombrado como tubería (ARCHIVOIARCHIVOO)
[ -r ARCHIVO ] ARCHIVO existe y tiene permisos de lectura
[ -s ARCHIVO ] ARCHIVO existe y tiene un tamaño mayor que 0
[ -t ARCHIVO ] La descripción del fichero de ARCHIVO está abierta y se refiere a una terminal
[ -u ARCHIVO ] ARCHIVO existe y tiene SUID asignado
[ -w ARCHIVO ] ARCHIVO existe y puede escribirse en él
[ -x ARCHIVO ] ARCHIVO existe y es un ejecutable
[ -O ARCHIVO ] ARCHIVO existe y está gestionado por su usario
[ -G ARCHIVO ] ARCHIVO existe y está gestionado por su grupo
[ -L ARCHIVO ] ARCHIVO existe y es enlace simbólico
[ -N ARCHIVO ] ARCHIVO existe y se modificó desde la última vez que se leyó
[ -S ARCHIVO ] ARCHIVO existe y es un socket
[ ARCHIVO1 -nt ARCHIVO2 ] ARCHIVO1 se modificó antes que ARCHIVO2, o si ARCHIVO1 existe y ARCHIVO2 no
[ ARCHIVO1 -ot ARCHIVO2 ] ARCHIVO1 es más viejo que ARCHIVO2, o ARCHIVO2 existe y ARCHIVO1 no
[ ARCHIVO1 -ef ARCHIVO2 ] ARCHIVO1 y ARCHIVO2 se refieren al mismo dispositivo y número de inodo
[ -o OPNAME ] Si la shell tiene la opción "OPTIONNAME" activdada bash -o
[ -z STRING ] La longitud del STR es 0
[ -n STRING ] ó [ STRING ] Si la longitud de STRING no es 0
[ STR1 == STR2 ] ó [ STR1 = STR2 ] Si las cadenas son iguales
[ STR1 != STR2 ] Si las cadenas no son iguales
[ STR1 < STR2 ] STR1 se ordena antes que STR2 según como esté la localización configurada
[ STR1 > STR2 ] STR1 ordena después de STR2 en base al idioma del sistema

Expresiones para números

Las siguientes condiciones solo son aplicables para números enteros, y devolverán verdadero en caso de cumplir la condición.

Expresión en terminal Descripción
[ N1 -eq N2 ] N1 es igual que N2
[ N1 -ne N2 ] N1 no es igual a N2
[ N1 -lt N2 ] N1 es menor que N2
[ N1 -le N2 ] N1 es menor o igual que N2
[ N1 -gt N2 ] N1 es mayor que N2
[ N1 -ge N2 ] N1 es mayor o igual que N2

Comparando múltiples valores

Se pueden anidar condiciones para un determinado valor o conjunto de valores como podemos ver a continuación gracias a los operadores lógicos.

cmd1 && cmd2 => Si devuelve 0 (éxito), se ejecutará cmd2 cmd1 || cmd2 => Si devuelve un número distinto a 0, se ejecutará cmd2

Expresión en terminal Descripción
[[ VAL1 -eq VAL2 && VAL3 -lt VAL1 ]] Si el VAL1 es igual a VAL2 y a su vez, VAL3 es menor que VAL1, devolverá verdadero
[[ VAL1 == VAL2

Referencias

  • Ediciones ENI ~ Tercera edición LPIC-I
  • The Linux Documentation Project ~ TLDP
  • Linux Man Pages ~ help if

Mastering en Bash - Enlaces simbólicos o duros y alias

En Echemos un bitstazo sabemos que no es así realmente el refrán, pero si que es cierto, que si acortamos mucho nos será más fácil aprendernos dónde está cada cosa haciendo uso de los enlaces para los ficheros y directorios y alias para comandos muy largos.

Alias

Los alias nos permiten reducir la longitud de una sentencia que queramos ejecutar en nuestro sistema y atajarla con una simple palabra. Por ejemplo, si queremos acceder a un directorio muy concurrido desde terminal.

cd ~/Documentos/Archivos/2018/05/10/10-11/Sector/1/ficheros_importantes/Codigo054/Area_51/

No nos imaginamos en absoluto tener que teclear toda esta ruta cada vez que queramos acceder al directorio Area_51. Pues podemos generar un alias, a nivel de sistema o a nivel de nuestro usuario.

A nivel de sistema, tenemos que añadirlo en /etc/bashrc si es que queremos que ese alias también lo tengan el resto de usuarios o si solo lo queremos para el nuestro, en ese caso, ~/.bashrc es el que debemos tocar de la siguiente manera:

alias nombre_alias='cd ~/Documentos/Archivos/2018/05/10/10-11/Sector/1/ficheros_importantes/Codigo054/Area_51/'

Posteriormente aplicamos los cambios:

source /etc/bashrc

o si es a nivel usuario:

source ~/.bashrc

Enlaces

Los enlaces vienen a ser lo que en Windows tenemos como "Accesos directos" pero a nivel de terminal, podemos especificar un directorio o un archivo que se encuentre en un directorio X pero teniendo un acceso más rápido en un directorio en el que trabajemos. También tenemos enlaces simbólicos que son accesos que si es borrado el archivo o directorio original solo queda el enlace y por lo tanto, no funciona y no es útil, o tenemos lo que denominamos enlaces duros, en los que se conserva una copia del fichero o directorio.

Simbólicos

Para poderlos generar, simplemente tenemos que hacer uso del comando ln(1) con el parámetro -s de soft.

ln -s /directorio_a_enlazar /directorio_donde_quiero_ver_el_enlace

Por ejemplo:

ln -s /usr/src ~

Nos genera un enlace simbólico hacia el directorio /usr/src de nuestro /home.

¿Cómo averiguar si dispongo del enlace simbólico? Cuando hacemos un ls(1) para listar documentos y directorios, veremos en una de las líneas de salida un dato similar:

lrwxrwxrwx.  1 sincorchetes sincorchetes         9 May 20 17:37  src -> /usr/src/
  • "l" al principio de esta entrada identifica un enlace simbólico.
  • src -> /usrc/src: Nos dice hacia dónde apunta.

Duros

Los enlaces duros permiten crear "una copia" de lo enlazado, de tal forma, que si se destruye el archivo o directorio original contínua funcionando.

ln /directorio_a_enlazar /directorio_donde_quiero_ver_el_enlace

De hecho, si hacemos un ls(1), no veremos añadida una l en los permisos o en acceso tipo src -> /usr/src.

Referencias

  • manpages, ln(1) y ls(1)

Mastering en Bash - grep y sus amigos

Volvemos a la carga

Como hemos comentado en el post anterior relacionado con este Mastering, queríamos dedicarle una publicación directamente a los comando grep(1) y cut(1), pues aquí esta uno de ellos. Ya hemos visto lo siguiente en este Mastering en Bash: * Qué es una shell y qué es Bash * Qué son las entradas y salidas en una shell * Qué son los modificadores en los comandos * Trabajando con directorios y archivos * Mostrando archivos ocultos * Qué son las rutas absolutas y relativas * Cómo posicionarse en directorios superiores * Obtener la ruta del directorio actual * Gestionando directorio: crear, mover, copiar, renombrar, eliminar * Listar archivos y directorios * Tipos de archivo * Crear ficheros vacíos * Mostrando información de un fichero * Trabajando con archivos de texto: * Mostrar o redireccionar texto * Crear archivo y añadir texto directamente * Copias de seguridad * Qué son las tuberías y redireccionamiento

Y todavía nos faltan muchos comandos y sobre todo, el área de scripting que es el área dónde pondremos en práctica lo aprendido para que nos pueda ser útil en un futuro.

Comando grep(1)

Este es uno de los comandos más esencial de Bash, nos permite mostrar coincidencias en archivos en base a la cadena de caracteres que nosotr@s le pasemos, en otras palabras, si queremos buscar una palabra en un archivo de texto, grep(1) es nuestro comando.

Sintaxis y ejemplos

Acorde con las indicaciones que nos proporciona la todopoderosa biblia de los comandos, man(1) estos son 3 ejemplos que nos da man 1 grep.

grep [OPCIONES] PATRÓN [FICHERO...]
grep [OPCIONES] -e PATRÓN ... [FICHERO...]
grep [OPCIONES] -f FICHERO ... [FICHERO...]

Tanto las opciones, como los patrones y los ficheros se pueden repetir dentro de la línea de ejecución de nuestro comando.

Vamos con los ejemplos:

grep -o "Linux" /proc/version

Imprimirá la cadena "Linux" si la encuentra en el archivo, y la imprime tantas veces como la encuentre.

grep -q "Linux" /proc/version

No imprime nada, es una opción en la que se omite la salida, si encuentra una coincidencia con dicha palabra, devolverá en el estado de la shell un 0. echo $? = 0 si se encontró y = 1 en el caso contrario.

grep -H "sda" /proc/* 2>/dev/null

Muestra en cada línea en la que encuentre coincidencias, también el nombre del archivo y omite errores.

grep -A 2 "_this_module" /proc/kallsyms

Muestra las 2 líneas siguientes de haber encontrado la coincidencia en la o las líneas.

grep -B 2 "_this_module" /proc/kallsyms

La inversa de la anterior, en vez de mostrar las 2 líneas siguientes, muestra las dos líneas anteriores a la coincidencia.

grep -C 2 "_this_module" /proc/kallsyms

Si la A y la B hacía cada cosa por separado, con la C podemos mostrar tanto las líneas anteriores como las posteriores. En este caso muestra el resultado de las dos sentencias anteriores en una sola sentencia.

grep -rA 2 "gcc" /proc/ 2>/dev/null

Buscará de forma recursiva en todos los ficheros y directorios que se encuentren dentro del directorio especificado y cuándo obtenga una coincidencia, imprimirá las 2 líneas anteriores a la coincidencia incluyendo el nombre del archivo en el que se encuentre.

NOTA: El uso del parámetro -r ya incluye el parámetro -H por defecto

grep -U "note" /bin/cp

Pretendemos encontrar una coincidencia dentro de un binario, y que en caso de encontrarla, ésta nos lo diga mediante un mensaje de salida.

grep -ob "root" /etc/passwd

Nos mostrará las líneas en dónde la coincidencia se haya repetido n veces dentro de un fichero especificado.

grep -obrA 2 "root" /etc 2>/dev/null

Permite efectuar lo mismo, pero se visualizarán las 2 líneas en cada coincidencia encontrada, número de línea, nombre de archivo dentro de un directorio y se omitirán los mensajes de error.

grep -FrB 2 '/usr' /proc 2>/dev/null

Permite utilizar caracteres especiales para la búsqueda de coincidencias. Este comando buscará de forma recursiva la cadena que contiene un carácter "prohibido" y mostrará las 2 líneas anteriores cada vez que encuentre una coincidencia. También omitirán los mensajes de error.

grep -ErC 2 '??linux' /proc 2>/dev/null

Al contrario que el anterior, aquí utilizaremos expresiones regulares como es el caso de ?? que sustituye a un caracter por signo de interrogación que no recordemos o no estemos seguro de cuál puede ser. Esta sentencia imprimirá las dos líneas siguientes a las coincidencias así mismo como las 2 anteriores, los mensajes de error se omitirán y se visualizará el nombre de los archivos que contengan dichas coincidencias

Los amigos de grep, fgrep(1) y egrep(1)

Pues ya los hemos dado en los dos ejemplos anteriores, aunque no lo creamos, fgrep(1) como egrep(1) son dos comandos que actúan como alias. * fgrep(1) equivale a grep -F * egrep(1) es igual a grep -E

Fuentes

  • man pages ~ grep(1)

Mastering en Bash - Primero de Scripting

Hace un mes más o menos que empezamos a ver cómo operar con Bash utilizando comandos básicos, ya podemos decir que sabemos más que antes y podemos dar el paso al Scripting. ¿Qué es el "Scripting"? Para nosotros es la habilidad que uno tiene para desarrollar un fichero de texto plano con el fin de automatizar determinadas tareas dentro del sistema. Y un script es el nombre que recibe este fichero.

Cuando hablamos de automatizar tareas, hablamos de que en vez de escribir 6 veces las operaciones que solemos efectuar día a día, un cambio de permisos, nuev@ usuari@...etc podemos crear un script que con tan solo ejecutarlo, lo haga todo por nosotr@s.

¿Cómo aprender?

Realmente cuando hablamos de desarrollo se traduce literalmente en por mucho que sepas, siempre aprenderás. Porque se te olvida un done en bucle, fi en un condicional, una variable mal declarada...etc, esto es así y hay que sumarle que debemos estar constantemente mirando otros scripts elaborados por terceras personas, practicar siempre que podamos porque esto nos ayudará a fianzar más los conocimientos que hemos aprendido aquí. Esto no es como memorizar un texto, haces examen y ¡ciao! ¡Implican muchas cosas! Como comprender conceptos abstractos, saber qué implica la ejecución de determinados comandos, conocer el sistema...etc

Pero no tenemos de que preocuparnos, todo es posible. Ahora le daremos paso a las variables y arrays

Variables, ¿Qué son?

Las variables como hemos visto en su día en matemáticas, es un conjunto de caracteres alfanuméricos (peras, melones, X1, abc12) cuyo valor asignado varía o está sujeto a algún cambio.

En Bash las variables las podemos declarar directamente o mediante el uso del comando declare(1) que lo hablaremos más adelante ya que permite generar diferentes tipos de categories: ["Administración de sistemas"]


¡Empezamos la recta final!

Hace un mes más o menos que empezamos a ver cómo operar con Bash utilizando comandos básicos, ya podemos decir que sabemos más que antes y podemos dar el paso al Scripting. ¿Qué es el "Scripting"? Para nosotros es la habilidad que uno tiene para desarrollar un fichero de texto plano con el fin de automatizar determinadas tareas dentro del sistema. Y un script es el nombre que recibe este fichero.

Cuando hablamos de automatizar tareas, hablamos de que en vez de escribir 6 veces las operaciones que solemos efectuar día a día, un cambio de permisos, nuev@ usuari@...etc podemos crear un script que con tan solo ejecutarlo, lo haga todo por nosotr@s.

¿Cómo aprender?

Realmente cuando hablamos de desarrollo se traduce literalmente en por mucho que sepas, siempre aprenderás. Porque se te olvida un done en bucle, fi en un condicional, una variable mal declarada...etc, esto es así y hay que sumarle que debemos estar constantemente mirando otros scripts elaborados por terceras personas, practicar siempre que podamos porque esto nos ayudará a fianzar más los conocimientos que hemos aprendido aquí. Esto no es como memorizar un texto, haces examen y ¡ciao! ¡Implican muchas cosas! Como comprender conceptos abstractos, saber qué implica la ejecución de determinados comandos, conocer el sistema...etc

Pero no tenemos de que preocuparnos, todo es posible. Ahora le daremos paso a las variables y arrays

Variables, ¿Qué son?

Las variables como hemos visto en su día en matemáticas, es un conjunto de caracteres alfanuméricos (peras, melones, X1, abc12) cuyo valor asignado varía o está sujeto a algún cambio.

En Bash las variables las podemos declarar directamente o mediante el uso del comando declare(1) que lo hablaremos más adelante ya que permite generar diferentes tipos de

Restricciones y usos

Por norma general, las variables en mayúsculas se reservan para temas de administración y gestión del sistema.

Si utilizamos el comando env(1), veremos toda la ristra de variables de entorno que tenemos:

LANG=en_US.utf8
GDM_LANG=en_US.utf8
HISTCONTROL=ignoredups
DISPLAY=:0.0
GUESTFISH_RESTORE=\e[0m
HOSTNAME=set0.lan
GTK_OVERLAY_SCROLLING=0
COLORTERM=truecolor
GUESTFISH_INIT=\e[1;34m
IMSETTINGS_INTEGRATE_DESKTOP=yes
KDEDIRS=/usr
XDG_VTNR=1
SSH_AUTH_SOCK=/home/sincorchetes/.cache/keyring-RYPSKZ/ssh
XDG_SESSION_ID=2
XDG_GREETER_DATA_DIR=/var/lib/lightdm-data/sincorchetes
USER=sincorchetes
GUESTFISH_PS1=\[\e[1;32m\]><fs>\[\e[0;31m\] 
DESKTOP_SESSION=mate
PT7HOME=/opt/pt
[SALIDA ACORTADA]

No pueden empezar con números, signos @#~½!, deberán comenzar con al menos una letra y luego si es posible usar números:

Ejemplo de errores:

@hola=23
h!ola=23
#o#=23
3hola=23

Correcto:

hola=23
h014=23
hola="Esto es un valor"

Declarando variables con texto

Si queremos añadir valores con cadenas a las variables, es muy importante comprender estas dos diferencias. Podemos declarar ambas con doble comillado "", ó, comillado simple ''. El problema erradica, en que no son lo mismo, el ("") permite mostrar el contenido de una variable dentro de un texto, mientras que ('') interpreta el texto tal cual.

$hw = "Hello World"
echo "$hw for everyone"

Hello World for everyone
$hw = "Hello World"
echo '$hw for everyone'
$hw for everyone

Visualizando las variables de entorno/sistema

Tenemos a nuestra disposición el comando env(1) que nos enseña todas las variables de entorno y de sistema que debemos respetar, vamos a comentar algunas de ellas.

Nombre de la variable Descripción
HOME Ruta de trabajo del usuario actual
PATH Lista de directorios dónde el shell buscará ejecutables (binarios, scripts...)
PS1 Prompt String 1, muestra el caracter, texto previo a la introducción de los comandos. [sincorchetes@set0 ~]$
PS2 Prompt String 2, Prompt secundario, por ejemplo, si se nos olvidan " cat -f file, cerrar el doble comillado, nos aparecerá el caracter o el prompt esperando a que cerremos la petición con otra doble comilla por ejemplo.
IFS Internal Field Separator, separadores como tabulación, espacio, salto de línea, si está en blanco, se usan espacios
MAIL Ruta y archivo de los mensajes del (la) usuari@ que tienen que ver con el e-mail
SHELL Ruta del shell del usuario
LANG Idioma y codificación
USER Variable que identifica al/la usuari@ actual
LOGNAME Nombre del login utilizado en inicio de sesión, por lo general suele ser el mismo que $USER
HISTFILE Ruta de archivo del historial de comandos ejecutados en la shell
HISTSIZE Tamaño del archivo historial de comandos ejecutados en shell
OLDPWD Directorio accedido anteriormente
PWD Ruta actual
RANDOM Genera un número aleatorio comprendido entre 0 y 31767

Eliminando una variable

Para eliminar una variable y su contenido, bastará con ejecutar el comando:

unset variable

Variable con acceso solo lectura

Se puede establecer una variable cuyo contenido no cambia como si fuese una constante haciendo uso del comando readonly(1)

readonly ejemplo=2

Visualizando el contenido de una variable

Para visualizar una variable, bastará con utilizar el comando echo(1).

ejemplo="Hola que tal"

echo $ejemplo

Convertir una variable en global

En desarrollo, se puede entender variable global como aquella que es accesible en todo momento por el programa a pesar de encontrarse en una función de manera cerrada, y una variable local aquella que solo se produce una vez y posteriormente, una vez efectuada la ejecución del bloque de código acaba por auto-suprimirse como un mensaje del inspector Gadget.

Para poder hacerla accesible deberemos hacer uso del comando source(1). Si tenemos un archivo con variables y queremos cargarlas, bastará con ejecutar:

source ruta_script

Y podremos acceder desde dónde queramos desde la shell dónde hayamos ejecutado dicho comando.

Utilizando variable para ayudarnos con los comandos

Por supuestísimo que podemos hacer uso de las variables para obtener una automatización.

ejemplo=`pwd`
ls $ejemplo

NOTA: No obstante, si tratamos de copiar archivos, directorios cuyas rutas se encuentran en variables, puede dar error, y es porque interpreta uno de los dos el nombre tal cual dando error. Para ello tendremos que utilizar el {}.

ruta_archivo_origen = /etc/group
ruta_archivo_destino = /home/$USER/Documentos

cp ${ruta_archivo_origen} ${ruta_archivo_destino}

Sustituir cadenas en variables

Podemos sustituir los valores que se encuentran en las variables sin tener que reasignarlas, solo utilizando llaves.

Si la variable está vacía o no existe, el texto se autoasignará. Probaremos con una variable cualquiera que al hacerle un echo(1) no mostrará valor alguno. Si está definida, mostrará el valor de la variable.

echo $ejemplo

Posteriormente efectuamos:

echo ${ejemplo:-Está aprobado}
Está aprobado

Pero el valor y la variable desaparecen. Si está definida, mostrará el valor de la variable. Si queremos que perduren, haremos los siguiente:

echo ${ejemplo:=Está aprobado}
Está aprobado
echo $ejemplo
Está aprobado

Por otro lado, si nos encontramos con una variable previamente declarada, pero no vacía, se puede sustituir utilizando el ":+", no es un cambio permanente.

echo ${PS1:+[${USER}@`pwd`]}

Y por último, si tenemos una variable que está vacía o que no exista, se interrumpe el script y mostrará el mensaje de error que le asignemos, si existe, devolverá el contenido de la variable:

echo ${dsfsd:?[${USER}@`pwd`]}
bash: dsfsd: [sincorchetes@/home/sincorchetes]

Obtener el valor de una cadena

Si queremos obtener el número de caracteres que constituyen el valor de una variable podemos hacerlo:

ejemplo="Hola que tal"
echo ${#ejemplo}
12

Operaciones aritméticas con variables

Se pueden hacer operaciones aritméticas con variables si primeramente declaramos el tipo de dato a través del comando typeset(1).

Operador Función
+ - * / Sumar, restar, multiplicar, dividir
% Nos da el módulo de la operación
< > <= => Establece comparaciones, 1=True; 0=False
== Igual que
!= Diferente de

Mostrar el resultado de la siguiente suma:

typeset -i a
a=1200+2200

echo $a
3200

¿Son iguales estos resultados?

typeset -i resultado
a=1200
b=1200
resultado=${a}==${b}

echo $resultado
1

Podemos encontrar muchos más operadores help let.

Variables especiales

No se pueden utilizar, suelen ser de solo lectura y notifican de algo ocurrido por lo general.

Saber si un comando se ejecutó con éxito o nop

echo $?

Nos devolverá un código al haber ejecutado un comando. Por lo general, 0 es que se ejecutó con éxito, 1 falló la ejecución del comando, 127 no encontró el ejecutable. Según el comando, ejecutable, binario... devuelve un código de error distinto.

Obtener el PID del shell actual

El PID proviene de Process ID, es el número que identifica un proceso, (más adelante explicaremos qué son los procesos) de la shell actual

echo $$
25382

PID del último proceso iniciado en segundo plano

Si hemos ejecutado un binario y/o ejecutable en segundo plano, nos chivará el número de identificación de proceso.

echo $!
25982

Opciones del shell

Son las características que tiene habilitadas la shell por defecto, en Fedora muestran las siguientes:

echo $-
himBHs

El significado lo podemos encontrar bash(1), sección SHELL BUILTIN COMMANDS:

h: Recuerda la ubicación de los comandos a medida de que se buscan para ejecutarse. Activado por defecto. i: Interactiva m: Modo monitor. El control de trabajos está activado. B: El intérprete de comandos permite una expansión del uso de las llaves y las varibles. Por ejemplo, echo a{d,c,d,b}e devolverá ade ace abe. Viene habilitado por defecto. H: Permite sustituir el estilo del histórico de comandos, se habilita por defecto pero debe tener la característica de interactivo (i).

Arrays (vectores)

Los vectores, o también conocidos como arrays permiten almacenar un conjunto de datos en un solo espacio de la memoria. En otros lenguajes como PHP pueden anidarse y confinar múltiples conjuntos de datos dentro de un solo espacio de memoria creando arrays multidimensionales.

Sin embargo, en Bash, esto no es posible, ya que solo podremos crear vectores de una sola dimensión y sin un índice personalizado mediante su creación. a menos que declaremos la posición como el resultado de una variable (pagina1=1 = array[pagina1]="Valor"). El índice en este caso, se identifica mediante un número comprendido entre 0-(n) dónde "n" es el número de datos que hemos añadido cuando declaramos un array.

    $array = (a b c d )     Datos almacenados en cada una de las posiciones
      ^      \_|_|_|_/        /*----------------------*\
      |         |||          /   ==> a = 1234           \   
    Nombre     Datos        /    ==> b = "Hello world"   \
     del        de  -------*     ==> c = `pwd`           *
    Array    Declarados     \    ==> d = $resultado     /
                             \*-----------------------*/

En este caso, para acceder al valor de cada letra correspondiente, tendremos que hacer uso de: $nombre_array + [n]. Dónde n es la posición del dato que queremos obtener.

Ejemplo:

echo $array[0]
|
|----> Obtendremos: 1234
echo $array[1]
|
|----> Obtendremos: Hello world
echo $array[2]
|
|----> Obtendremos: /home/sincorchetes (en mi caso)

¿Cómo obtener la longitud de un array?

Básicamente, de la siguiente forma:

echo ${#array[*]}

Nos tendrá que dar como resultado "4", que son los valores declarados. (a= 1234, b = "Hello world"...)

¿Cómo obtener todos los valores de un array?

Sustituiremos el número de la posición por una @.

echo ${array[@]}

¿Cómo añadir un nuevo valor a un índice específico de un array declarado?

Bastará con mencionar el número de posición que queremos asignar el nuevo dato:

$array[10]="Hola que tal"

Visualizar el número de posiciones ocupadas dentro de un array

Simplemente si queremos ver que posiciones están ocupadas para utilizar las que estén libres:

echo ${!array[*]}

Ver cuánto tamaño contiene de largo una posición

Para comprobar el tamaño, simplemente hacemos:

echo ${#array[1]}

¿Cómo añadir un nuevo valor sin declarar posición en un array?

Simplemente si queremos añadir un dato nuevo sin especificar un índice en cuestión.

array+=(nuevo_valor)

Eliminar una posición del array

Utilizaremos el comando unset(1) como se ha utilizado para eliminar variables declaradas.

unset array[n]

Resultado de un comando que se separe como valores y que estos ocupen una posición dentro del array

Esto quiere decir, que si asignamos un solo valor, cuyo valor sea el resultado de un comando, este generará una salida y todos los datos expuestos en la salida del comando se convertirán en un valor dentro de una posición. Por ejemplo, si hacemos un cat /etc/group, obtendremos una salida similar a esta:

root:x:0:
bin:x:1:
daemon:x:2:
sys:x:3:
adm:x:4:
tty:x:5:
disk:x:6:
[SALIDA ACORTADA]

Bien, si le decimos al array que nos almacene esta lista para luego visualizarla, podemos hacerlo.

array=(`cat /etc/group`)

Si hacemos un echo ${array[0]} veremos que nos saldrá la primera línea del documento:

root:x:0:

Si queremos obtener toda la lista:

echo ${array[@]}

Y hasta aquí nuestra entrega de hoy.

Referencias

Mastering en Bash - Primeros pasos

Bash es un intérprete de comandos también conocido en inglés como una "shell" desarrollada el 8 de junio de 1989 por Brian Fox en el lenguaje C como alternativa y mejora de SH (Bourne Shell). Hoy en día es multiplataforma ya que puede correr tanto en Linux como en Mac OS X (de hecho es shell por defecto), en Windows mediante Cygwin o mediante la instalación oficial desde su apartado de añadir nuevas características de software.

Actualmente existen multitudes de I.C pero mencionaremos las más destacadas como: * csh: C Shell creada por Bill Joy, 1978 * tcsh: TENEX C Shell desarrollada por Ken Greer, 1981 * fish: Shell interactiva liberada el 13 de febrero de 2005 por Axel Liljencrantz * zsh: Z Shell elaborada por Paul Falstad en 1990 * ksh: KornShell creada por David Korn en 1983

Cada una de ellas contiene ciertos matices a la hora de desarrollar scripts que son un serie de ficheros que suelen contener comandos e intrucciones adicionales para que se puedan ejecutar sin tener que escribir grandes bloques de comandos, variables...

Entrada/Salida

Las entradas y salidas es algo que debemos tener claro desde el principio. Una entrada se produce cuando introducimos un comando y pulsamos ejecutar o un programa automatizado ejecuta un programa X.

La salida es el resultado producido al ejecutar dicho comando. Más adelante veremos, que podemos trabajar con salidas para que trabajen como entradas y viceversa.

Modificadores

Son las opciones con las que cambiaremos el comportamiento de los comandos y programas. Se identifican con un guión delante de una letra que hace referencia a una modificación.

Por ejemplo, ls -l lista todos los nombres de los directorios y de los archivos junto con información adicional como: * Permisos * Cantidad de dir hijos que hay dentro del directorio padre incluyendo así mismo y el padre * Grupo que gestiona el archivo/directorio * Usuario propietario * Nº de inodo * Fecha de modificación

Sin embargo, un ls (que es ls -a por defecto), mostrará solo el nombre de los archivos y directorios situados en el dir actual. NOTA: En artículos posteriores veremos con más profundidad qué son estos parámetros en los archivos.

Trabajando con Bash

A continuación veremos una recopilación de comandos básicos para poder trabajar con nuestra shell antes de poder seguir. Quizás nos pueda parecer un poco abrumador así de entrada todos los comandos, los modificadores, tipos de rutas...etc etc etc. Pero desde Echemos un bitstazo apostamos por el dicho de "la práctica hace al maestro". Y es así, mucho de nosotros que desarrollamos sufrimos una pérdida de memoria cuando dejamos de hacerlo. Así que... ¡Ha llegado la hora de practicar!

Directorios y archivos

En este apartado veremos como trabajar con los directorios dentro del sistema. Tenemos que tener en cuenta, de que la arquitectura estandar del sistema de ficheros en Linux (FHS) está organizada en modo de árbol. Esto quiere decir que todo cuelga de un directorio raíz llamado (/), del que cuelga el resto de ellos.

NOTA: Comentaremos los directorios más básicos y relevantes para este artículo, ya que debe dedicársele un post solamente para explicar qué funciones realiza cada directorio del sistema.

El directorio dónde por defecto se generan las carpetas para los nuevos usuarios del sistema se encuentra ubicado en /home. Por defecto, nuestra shell nos sitúa en el directorio principal de nuestro usuario, con lo que no tendremos que desplazarnos a niveles superiores dentro del sistema de archivos.

Archivos ocultos

Los archivos ocultos se representan por llevar un . como prefijo al nombre del archivo o directorio y no aparecerán listados con ningún comando por defecto. No necesita ningún tipo de modificador adicional para generarlos o para leerlos.

Rutas absolutas y relativas

Las rutas absolutas son aquellas que contienen la dirección completa dentro de la jerarquía del sistema de archivos. /home/sincorchetes/Videos/Echemosunbitstazo/capitulo1.ogg

Mientras que las rutas relativas, solo contienen una dirección breve que se muestra desde la propia carpeta. Imaginemos que estamos en el directorio /home/sincorchetes/ y queremos llegar hasta el capitulo1.ogg. Para ello tendríamos que apuntar de la siguiente manera: Echemosunbitstazo/capitulo1.ogg ó bien ./Echemosunbitstazo/capitulo1.ogg

Escalado entre directorios

Nosotros podemos aprovecharnos de algunos "alias" que nos provee la shell para agilizar la gestión o administración de directorios haciendo uso de las rutas relativas. Estos son algunos trucos: * .: Significa, el directorio actual. ls . devuelve una salida en la que mostrará todos los directorios y archivos en el directorio actual * ..: Sube un nivel superior, ls .. mostrará los directorios y archivos del directorio padre.

Obtener la ruta del directorio actual

Si queremos saber en qué directorio nos encontramos actualmente, bastará con ejecutar el comando:

$ pwd

pwd(1) proviene del inglés "print name of current/working directory", imprimir el nombre del directorio actual.

Creando un directorio

Con el siguiente comando generamos un directorio nuevo sin ningún tipo de contenido. Existe una sintaxis para crear directorios. No se puede empezar por caracteres especiales, aunque, dentro de los caracteres especiales se puede utilizar el espacio, pero se puede utilizar números, mayúsculas o minúsculas.

$ mkdir nombre_directorio

NOTA: En caso de que queramos crear un subdirectorio sin existir primero el directorio padre, nos dará error si lo ejecutamos tal cual. Para ello, deberemos aplicar la opción -p.

Desplazarnos entre directorios

Para poder desplazarnos entre directorios tenemos dos formas de hacerlo, mediante el comando UNIX por excelencia cd(1) o pushd(1) y popd(1).

Desplazándonos con cd(1)

Simplemente deberemos ejecutar el comando y la ruta ya sea relativa o absoluta a la que queramos acceder como en los siguientes ejemplos: * Situándonos en el directorio raíz del sistema: cd / * Subiendo un nivel del directorio actual: cd .. * Accediendo a /usr/local/share: cd /usr/local/share

Desplazándonos mediante pushd(1) y popd(1)

Uno de estos comandos tienen la ventaja de almacenar en la sesión de bash(1) actual el directorio y además, nos ubica en él como es el caso de pushd(1). Mientras que popd(1), nos permite volver hacia atrás en caso de no querer seguir estando en él.

Moviéndonos al directorio raíz:

$ pushd .themes/
~/.themes ~
$ pwd
/home/sincorchetes/.themes

Volviendo hacia atrás:

$ popd
 popd
~
$ pwd
/home/sincorchetes

Estos comandos tienen algunas características especiales que podemos consultarlas en el manual de cada uno de ellos.

Renombrando

Para cambiar de nombre, solo será necesario ejecutar el comando mv(1) junto con el directorio que queramos cambiar y el directorio con nuevo nombre. Se pueden emplear rutas relativas, absolutas o una combinación de ambas: * mv dir dir_nuevo_nombre * mv dir /home/sincorchetes/nuevo_nombre * mv /home/sincorchetes/dir /home/sincorchetes/nuevo_nombre

NOTA: Hay que tener cuidado con utilizar mv(1) porque también sirve para mover directorios.

Moviendo

Para desplazar directorios o archivos, tan solo tendremos que hacer uso de nuevo del comando mv(1).

  • mv archivo.ogg /home/sincorchetes/Videos/Echemosunbitstazo
  • mv archivo.ogg Videos/Echemosunbitstazo
  • mv /home/sincorchetes/archivo.ogg Videos/Echemosunbitstazo

También se puede aplicar un renombre más traslado: * mv archivo.ogg /home/sincorchetes/Videos/Echemosunbitstazo/nuevo_nombre.ogg * mv archivo.ogg Videos/Echemosunbitstazo/nuevo_nombre.ogg * mv /home/sincorchetes/archivo.ogg Videos/Echemosunbitstazo * mv /home/sincorchetes/archivo.ogg /home/sincorchetes/Videos/Echemosunbitstazo

Copiando

En el caso de copiar archivos, tenemos el comando cp(1). También puede aplicarse el uso de rutas absolutas, relativas o un conjunto de las mismas. cp archivo directorio_a_copiar

Es importante destacar, que para copiar un directorio completo a pesar de que esté vacio. Hagamos uso del modificador -r o -R (recursivo)

También dispone de un modo interactivo utilizando el modificador -i

Listar archivos y directorios

El comando por excelencia en estos casos es ls(1) Nos permite listar con multitudes de opciones si utilizamos los modificadores.

  • Listar todos los archivos incluyendo los ocultos con la información que muestra ls -l: ls -al
  • Mostar el nombre de todos los archivos incluyendo la representación del espacio como caracter escapado: ls -b
  • Mostrar el nombre de todos los archivos en una sola columna: ls -w 1

Tipo de archivo

En contra posición de sistemas como Windows, en Linux se puede tener un archivo sin ningún tipo de extensión. El sistema se encarga de averiguar que tipo de archivo es y abrirlo con la aplicación correspondiente.

Si queremos saber algún día si nos han enviado un ejecutable o un audio realmente, haremos uso del comando file(1)

Crear un fichero vacío

Aunque la auténtica utilidad del comando touch(1) es modificar la fecha y hora de los archivos. También se puede utilizar para crear un fichero vacío y añadir texto posteriormente. touch fichero_nuevo

Mostrando información de un fichero

Si queremos leer un archivo de texto plano como la configuración de un servidor Apache, haremos uso del comando cat(1).

cat /etc/profile

Salida truncada:

# /etc/profile

# System wide environment and startup programs, for login setup
# Functions and aliases go in /etc/bashrc

# It's NOT a good idea to change this file unless you know what you
# are doing. It's much better to create a custom.sh shell script in
# /etc/profile.d/ to make custom changes to your environment, as this
# will prevent the need for merging in future updates.

pathmunge () {
    case ":${PATH}:" in
        *:"$1":*)
            ;;
        *)
            if [ "$2" = "after" ] ; then
                PATH=$PATH:$1
            else
                PATH=$1:$PATH
            fi
    esac
}

Trabajando con texto

Mostrar o redireccionar texto

Bash nos permite mostrar una frase, un texto que queramos gracias al comando echo(1).

echo "¡No nos perderemos los nuevos artículos de Echemosunbitstazo!"

También podemos redirigir el texto a un archivo nuevo echo "¡No nos perderemos los nuevos artículos de Echemosunbitstazo!" > /home/sincorchetes/Documentos/archivo_nuevo

Añadir información a un archivo ya existente echo "¡No te pierdas él próximo día otro capítulo más sobre Bash en echemosunbitstazo.es" >> /home/sincorchetes/Documento/existente

Crear un archivo y añadir texto directamente

Podemos hacer uso del comando cat(1) para finalizar la edición, tendremos que finalizarla pulsando la combinación de teclas CTRL+D y para ello de la siguiente manera:

cat >fichero_de_ejemplo
Esto es un ejemplo.

Copias de seguridad

El comando por excelencia para elaborar copias de seguridad en Linux es haciendo uso del comando tar(1)

Elaborando copias de seguridad

Elaborando una copia de un directorio tar cfv copia_seguridad.tar dir1 dir2 archivo1 archivo2...

Comprimir con bzip2 tar cfvj copia_Seguridad.tar.bz2 dir1 dir2 arch1 arch2...

Utilizar compresión gzip tar cfvz copia_seguridad.tar.gz dir1 dir2 arch1 arch2...

Crear una copia de seguridad con formato xz tar cfvJ copia_seguridad.tar.xz dir1 dir2 arch1 arch2...

Descomprimiendo copias de seguridad

A la hora de descomprimir las copias de seguridad no tenemos que declarar el tipo de formato en el que está comprimido, con lo que ganamos más tiempo para dedicarlo a otras cosas.

Para Descomprimir una copia de seguridad tar xfv copia_seguridad.tar

Fuentes

Mastering Bash - Redireccionamientos y tuberías

Un redireccionamiento, como su propio nombre indica lo que hace es una redirección a un determinado sitio. En nuestro caso, utilizaremos los redireccionamientos para gestionar tanto las salidas, como entradas así como los niveles de error que de un comando o una aplicación para utilizarlos en nuestro beneficio.

Podemos decirle a un comando, que si tiene un error X, no lo muestre en pantalla y lo rediriga a un archivo de texto para que haga de log. También podemos añadir una frase, sentencias... a un archivo ya existente o en caso de que no exista que lo cree; comentar el número de palabras que tiene un texto... y un sin fin de cosas más.

Operadores de redireccionamiento

Estos son los operadores que utilizaremos en la elaboración de scripts sobre todo, capítulo que introduciremos estos días con las siguientes entregas.

Operador Descripción
> Redirecciona una salida hacia un archivo o comando. Si el archivo no existe, lo crea, y si existe, lo sobreescribe
>> Igual que el anterior, pero si el archivo existe no lo destruye, añade la salida después de la última línea
< Redirecciona una entrada hacia un comando para que este emita una salida (si lo hace), puede ser la salida de un comando hacia otro, un fichero...
<< Redirecciona el contenido de un fichero hasta que se encuentre la palabra especificada en la redirección para finalizarla

Canales

Nuestra terminal tiene una serie de canales por los que se toman la entrada, salida y errores.

| Canal | Descripción | Ubicación | |-------|-------------|-----|------| | 0 | Es el canal por defecto de la entrada estándar | /dev/stdin | | 1 | Especifica la salida de un comando. Por ejemplo ls 2> file.txt | /dev/stdout | | 2 | Muestra la presencia de errores. Por ejemplo ls -lklk 3> error.txt | /dev/stderr | categories: ["Administración de sistemas"]


Estamos de vuelta

Bienvenidos a esta nueva entrega de Mastering en Bash, los que ya nos siguen de las anteriores espero que disfrutéis con este post, si acabas de acceder y no tienes ni idea de que va esto, puedes ver nuestro viejo post Primeros Pasos. En el siguiente post veremos que son los redireccionamientos y las tuberías antes de comenzar con scripting.

¿Qué es un redireccionamiento?

Un redireccionamiento, como su propio nombre indica lo que hace es una redirección a un determinado sitio. En nuestro caso, utilizaremos los redireccionamientos para gestionar tanto las salidas, como entradas así como los niveles de error que de un comando o una aplicación para utilizarlos en nuestro beneficio.

Podemos decirle a un comando, que si tiene un error X, no lo muestre en pantalla y lo rediriga a un archivo de texto para que haga de log. También podemos añadir una frase, sentencias... a un archivo ya existente o en caso de que no exista que lo cree; comentar el número de palabras que tiene un texto... y un sin fin de cosas más.

Operadores de redireccionamiento

Estos son los operadores que utilizaremos en la elaboración de scripts sobre todo, capítulo que introduciremos estos días con las siguientes entregas.

Operador Descripción
> Redirecciona una salida hacia un archivo o comando. Si el archivo no existe, lo crea, y si existe, lo sobreescribe
>> Igual que el anterior, pero si el archivo existe no lo destruye, añade la salida después de la última línea
< Redirecciona una entrada hacia un comando para que este emita una salida (si lo hace), puede ser la salida de un comando hacia otro, un fichero...
<< Redirecciona el contenido de un fichero hasta que se encuentre la palabra especificada en la redirección para finalizarla

Canales

Nuestra terminal tiene una serie de canales por los que se toman la entrada, salida y errores.

| Canal | Descripción | Ubicación | |-------|-------------|-----|------| | 0 | Es el canal por defecto de la entrada estándar | /dev/stdin | | 1 | Especifica la salida de un comando. Por ejemplo ls 2> file.txt | /dev/stdout | | 2 | Muestra la presencia de errores. Por ejemplo ls -lklk 3> error.txt | /dev/stderr |

Ejemplos

Almacenar la salida del comando ls -al en un fichero lista.txt:

ls -al > lista.txt

Veremos como no se muestra nada en pantalla, pero se ha creado el archivo lista.txt

Mostrar el contenido de lista.txt

cat lista.txt
total 568
drwxrwxr-x.  2 sincorchetes sincorchetes  4096 May  2 01:43 .
drwx------. 55 sincorchetes sincorchetes  4096 May  2 17:10 ..
-rw-rw-r--.  1 sincorchetes sincorchetes 25277 May  1 12:55 20E2MC8SVX-9423.png
-rw-rw-r--.  1 sincorchetes sincorchetes 25277 May  1 12:55 36712GXM3C-865.png
-rw-rw-r--.  1 sincorchetes sincorchetes 25277 May  1 12:55 4SASA426RU.png
-rw-rw-r--.  1 sincorchetes sincorchetes 25277 May  2 01:43 5ODFPGZXOI-25637.png
-rw-rw-r--.  1 sincorchetes sincorchetes 25277 May  2 01:43 5PYBWDCZWK.png
-rw-rw-r--.  1 sincorchetes sincorchetes 25277 May  1 12:55 6A21WJKHWL.png

NOTA: Recordemos que el operador > sobreescribe todo lo que haya, si queremos añadir información nueva al archivo debemos utilizar el operador >>

ls -al >> lista.txt
cat lista.txt
total 568
drwxrwxr-x.  2 sincorchetes sincorchetes  4096 May  2 01:43 .
drwx------. 55 sincorchetes sincorchetes  4096 May  2 17:10 ..
-rw-rw-r--.  1 sincorchetes sincorchetes 25277 May  1 12:55 20E2MC8SVX-9423.png
-rw-rw-r--.  1 sincorchetes sincorchetes 25277 May  1 12:55 36712GXM3C-865.png
-rw-rw-r--.  1 sincorchetes sincorchetes 25277 May  1 12:55 4SASA426RU.png
-rw-rw-r--.  1 sincorchetes sincorchetes 25277 May  2 01:43 5ODFPGZXOI-25637.png
-rw-rw-r--.  1 sincorchetes sincorchetes 25277 May  2 01:43 5PYBWDCZWK.png
-rw-rw-r--.  1 sincorchetes sincorchetes 25277 May  1 12:55 6A21WJKHWL.png
-rw-rw-r--.  1 sincorchetes sincorchetes 25277 May  2 01:43 6FG92BUEDM-12977.png
-rw-rw-r--.  1 sincorchetes sincorchetes 25277 May  2 01:43 A6XZFBO1TK-18309.png
-rw-rw-r--.  1 sincorchetes sincorchetes 25277 May  2 01:43 FBEBPAR2O9-16637.png
-rw-rw-r--.  1 sincorchetes sincorchetes 25277 May  2 01:43 FP9EZ05Y3E-16753.png
-rw-rw-r--.  1 sincorchetes sincorchetes 25277 May  1 12:55 FZRD6D42BI-875.png

Guardar todos los errores que surjan en la ejecución del programa

cat ks 2> error.txt

No se mostrará nada en pantalla, pero nos daremos cuenta el error que nos da cat(1) en el fichero que se ha creado llamado error.txt

cat error.txt
cat: jk: No such file or directory

Mostrar en pantalla tanto la salida estándar como los errores

ls -al 2>&1 info.txt

Guardar en un fichero tanto la salida como los errores

ls -al 2>&1 info.txt > file.txt

Calcular las líneas que tiene un fichero de texto

wc -l < file.text

Añadir información a un fichero e interrumpirlo utilizando una palabra clave declarada por el usuario

cat add << EOF

Crear un fichero de texto utilizando la canal de entrada y utilizando una palabra clave para finalizar la adicción

cat > create_text.txt << EOF

Adherir la salida estándar de múltiples textos y redireccionándolos a un archivo

cat lista.txt error.txt info.txt create_text.txt > salida_multiple

Tuberías

Una tubería es una secuencia de uno o más comandos separados por operadores de control como | o &. Suelen utilizarse mucho junto con el comando grep(1), egrep(1) y fgrep(1) para filtrar resultados, o el comando cut(1) para recortar la salida estándar, generalmente producida por comandos. Estos comandos que hemos mencionado les dedicaremos un post especial debido a la importancia de los mismos. Sobre todo cuando demos scripting más adelante.

Este es el formato de una tubería común:

comando [+parámetros] | ó & [comando1]

Ejemplos

Ejemplos basándonos en esta estructura de directorios:

.
├── fichero-0
├── fichero-1
├── fichero-10
├── fichero-11
├── fichero-12
├── fichero-13
├── fichero-14
├── fichero-15
├── fichero-16
├── fichero-17
├── fichero-18
├── fichero-19
├── fichero-2
├── fichero-3
├── fichero-4
├── fichero-5
├── fichero-6
├── fichero-7
├── fichero-8
└── fichero-9

Mostrar un valor relacionado con dmesg(1)

dmesg |grep Bluetooth

[   23.265232] Bluetooth: Core ver 2.22
[   23.265247] Bluetooth: HCI device and connection manager initialized
[   23.265250] Bluetooth: HCI socket layer initialized
[   23.265251] Bluetooth: L2CAP socket layer initialized
[   23.265256] Bluetooth: SCO socket layer initialized
[   24.078796] Bluetooth: hci0: read Intel version: 370810225019140f18
[   24.078797] Bluetooth: hci0: Intel device is already patched. patch num: 18
[   35.047963] Bluetooth: BNEP (Ethernet Emulation) ver 1.3
[   35.047967] Bluetooth: BNEP filters: protocol multicast
[   35.047974] Bluetooth: BNEP socket layer initialized
[   85.419671] Bluetooth: RFCOMM TTY layer initialized
[   85.419675] Bluetooth: RFCOMM socket layer initialized
[   85.419722] Bluetooth: RFCOMM ver 1.11
[60146.891379] Bluetooth: hci0: read Intel version: 370810225019140f00
[60147.826024] Bluetooth: hci0: Intel Bluetooth firmware file: intel/ibt-hw-37.8.10-fw-22.50.19.14.f.bseq
[60148.097374] Bluetooth: hci0: Intel firmware patch completed and activated
[60151.506132] Bluetooth: hci0: command 0x0c56 tx timeout

Mostrar un valor relacionado con la salida del comando lspci(8)

lspci |grep VGA
00:02.0 VGA compatible controller: Intel Corporation Device 591b (rev 04)

Referencias

Mastering en Bash - Trabajando con textos

En esta entrega vamos a ver como trabajar con textos en Bash, tenemos una serie de comandos para trabajar con ellos que nos ayudarán cuando estemos avanzando en nuestra senda por este querido mundo que es el Software Libre.

Comando less(1)

Este comando se utiliza mucho para visualizar textos desde el principio. Nos podemos olvidar de hacer un cat(1) y empezar a subir la parrafada bien con un scroll en una terminal gráfica o bien haciendo uso de Shift + Page Up/Page Down.

Su funcionamiento es sencillo, simplemente con las teclas de dirección podemos orientarnos en el texto. No obstante, veremos el funcionamiento de algunos atajos del teclado:

Métodos abreviados Descripción
j ó Desplaza una línea hacia delante o una cantidad "N"
k ó Desplaza una línea o una cantidad N hacia atrás
SPACE Desplaza un conjunto de muchas líneas o varios conjuntos hacia delante
b Igual que el anterior, pero desplazándolas hacia detrás
Desplaza la mitad del ancho de una pantalla o N posiciones
Desplaza la mitad del ancho de una pantalla o N posiciones (solo valido si se utiliza
F Actuando como tail -f
/ Permite buscar coincidencias

Aquí podemos ver el funcionamiento de less(1) en acción:

Comando more(1)

Este comando es parecido a less(1), lo que pasa es que se diferencia sobre todo en su apariencia como el cuadro de ayuda que es distinto pero la finalidad llega a ser la misma, mostrar texto. Comentamos los atajos de teclado más utilizados:

Métodos abreviados Descripción
+ Espacio Desplaza una línea hacia delante o una cantidad "N"
+ z Desplaza una línea o una cantidad N hacia atrás
SPACE Desplaza un conjunto de muchas líneas o varios conjuntos hacia delante
= Muestra la línea actual
/cadena Encuentra coincidencias
n Salta a la siguiente coincidencia
! Permite ejecutar un comando en una subshell
/ Inicia el editor vi(1) en la línea actual
:f Muestra el nombre del fichero y número de línea actual

Por aquí tenemos a more(1) un poco en acción:

Comando tail(1)

Este comando suele utizarse para mostrar salidas vivas en la terminal, es decir, si tenemos un archivo que constantemente se actualiza como pueden ser los logs, este nos permite ver a tiempo real los cambios producidos entre otras muchas más cosas.

En principio, si se ejecuta sin ningún parámetro o modificador, este devolverá un determinado número de líneas, unas 10 por defecto.

Veremos los modificadores más comunes:

Parámetros Descripción
-n N Modifica el límite de líneas a mostrar
-v Muestra el título del fichero como una cabecera
--version Muestra el número de versión

Comando tail en acción:

Comando head(1)

head(1) nos permite visualizar las 10 primeras líneas de la parte superior de los archivos, lo contrario a tail(1) y su funcionamiento es parecido, tanto que se pueden utilizar los parámetros de tail(1) para su uso.

Visualizando a head(1):

Comando wc(1)

Este es muy utilizado para contar líneas, decimales o bytes, suele combinarse con tuberías para obtener resultados y utilizarlos en condicionales por ejemplo. Veamos como funciona.

Parámetros Descripción
-c Imprime los recuentos de bytes de una salida o fichero
-m Recuentos de caracteres
-l Muestra el número de líneas calculado de un archivo o salida
-L Imprime el número de la línea más larga
-w Recuento de palabras

Veamos como funciona:

Comando tr(1)

Este comando nos permitirá intercambiar caracteres por otros o eliminarlos desde una salida. Por ejemplo, vamos a modificar la salida de una línea: head -n 3 /proc/kallsyms | tr 0 K

Nos dará un resultado como este:

KKKKKKKKKKKKKKKK A irq_stack_union
KKKKKKKKKKKKKKKK A __per_cpu_start
KKKKKKKKKKKKKKKK A cpu_debug_store

Si no queremos reemplazar el caracter y simplemente eliminarlo:

head -n 3 /proc/kallsyms | tr -d 0

Obtendremos una salida como esta:

 A irq_stack_union
 A __per_cpu_start
 A cpu_debug_store

Si queremos trabajar con caracteres especiales, podemos hacerlo.

Tenemos mucha info en el man 1 tr que nos puede ayudar.

Comando cut(1)

Este comando es uno de los más potentes, con el se hacen auténticos scripts, ya que nos permite eliminar secciones de ficheros o salidas.

Por ejemplo, si queremos obtener las variables declaradas en el archivo /etc/os-release

cut -f 1 -d "=" /etc/os-release

O si queremos que nos devuelvan los datos:

cut -f 2 -d "=" /etc/os-release

Podemos hacer combinaciones entre dos comandos para que nos devuelva exclusivamente los valores de las variables sin entrecomillado de este archivo.

cut -f 2 -d "=" /etc/os-release | tr -d '\"'

Básicamente cuando se utiliza el parámetro -f + NUM, es porque queremos escoger los resultados que se encuentren dentro de la columna número X y se utiliza con el modificador -d CARÁCTER para poder partir el resultado, si no no sirve de nada.

Fuentes

  • manpages

Transfersh sube archivos desde terminal

Si quieres compartir archivos desde Bash por ser un curioso, por subir ficheros de un servidor a otro sitio...etc puedes hacerlo mediante transfer.sh.

Este servicio permite alojar archivos de hasta 10GB de capacidad sin coste alguno. También añade una serie de características como seguridad (archivos alojados encriptados), obtienes una URL para descargar los archivos desde cualquier navegador y todo con un plazo de hasta ¡14 días!

Tan solo hay que utilizar curl(1), un programa parecido a wget(1), este permite transferir datos a servidores utilizando algúno de los protocolos soportados como DICT, FILE, FTP, FTPS, GOPHER, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET y TFTP). También tiene otras características como soporte para proxy, autenticación de usuari@s, conexión SSL, cookies...etc

¿Cómo funciona el servicio?

Bueno básicamente, con ejecutar:

curl --upload-file fichero_a_subir https://transfer.sh

Este devolverá una URL que apunta al fichero. También se puede hacer directamente, si añades en el apartado "Drag your files here, or click to browse." dará el mismo resultado via Web.

¿Cómo descargo el fichero?

Bien, puedes hacer un simple:

curl https://transfer.sh/NUMERO/NOMBRE_ARCHIVO -o NOMBRE_ARCHIVO

O bien, desde la propia Web.

¡A qué espera a probarlo!