ls
en estos momentos, habría cinco procesos y un
único programa.
ps
(process status):
<gyermo@ENCINA>/usuarios/profes/gyermo$ ps PID TTY TIME CMD 3991 pts/1 0:00 bash 4000 pts/1 0:00 psLa verdad es que el listado no es nada emocionante... Aparecen solamente dos procesos, un tal
bash
(luego veremos
que en realidad es femenino y debemos decir una tal
bash
) y el propio ps
, que sale
en su misma foto.
ps
. Lo usaremos para poder actuar sobre el proceso.
La segunda columna nos da el terminal. La tercera columna nos muestra
el tiempo de CPU o tiempo de trabajo útil que la
CPU ha dedicado al proceso y la cuarta columna es el nombre de la
orden.
-fcu
, como en este ejemplo:
<gyermo@ENCINA>/usuarios/profes/gyermo$ ps -fcu gyermo UID PID PPID CLS PRI STIME TTY TIME CMD gyermo 3989 3986 TS 59 18:12:42 ? 0:00 /usr/lib/ssh/sshd gyermo 3991 3989 TS 49 18:12:42 pts/1 0:00 bash gyermo 7188 3991 TS 49 18:27:21 pts/1 0:00 ps -fcu gyermoVemos que, con estas opciones, aparecen las columnas adicionales de UID (usuario que ejecuta el proceso), PPID (identificador del proceso padre del proceso), CLS (clase de proceso; TS=tiempo compartido), PRI (prioridad del proceso) y STIME (hora a la que fue lanzado).
-efc
.
Podéis combinar estas órdenes con lo ya aprendido.
Por ejemplo, para saber cuántos procesos hay en ejecución
en el sistema, podemos poner:
<gyermo@ENCINA>/usuarios/profes/gyermo$ echo $((`ps -efc | wc | cut -c 1-8`-1)) 43Evidentemente, no es un cálculo exacto, puesto que el propio
ps
, e incluso wc
y cut
, pueden
interferir, como procesos que son, en el resultado.
Es similar, salvando las distancias,
al conocido efecto de la mecánica cuántica
en que, para poder medir algo, el observador altera sin remedio
el resultado de su medida.
top
. Al invocarla
también se nos da información de los procesos, pero es
dinámica y, además ordena los procesos por consumo de
CPU.
load averages: 0.07, 0.10, 0.10 18:40:48 38 processes: 37 sleeping, 1 on cpu CPU states: 96.4% idle, 0.0% user, 3.6% kernel, 0.0% iowait, 0.0% swap Memory: 2048M real, 1511M free, 140M swap in use, 5429M swap free PID USERNAME LWP PRI NICE SIZE RES STATE TIME CPU COMMAND 9317 gyermo 1 59 0 4312K 2456K cpu 0:00 0.22% top 261 root 1 100 -20 2520K 1080K sleep 15:47 0.01% xntpd 239 daemon 4 59 0 81M 53M sleep 12:53 0.01% nfsmapid 3989 gyermo 1 59 0 8608K 2736K sleep 0:00 0.01% sshd 7 root 12 59 0 9312K 3856K sleep 2:30 0.00% svc.startd 3991 gyermo 1 59 0 3152K 2584K sleep 0:00 0.00% bash 427 root 2 59 0 5472K 2560K sleep 28.0H 0.00% bacula-fd 364 root 1 2 19 1576K 1048K sleep 255:15 0.00% pandora_agent 115 daemon 3 59 0 4816K 2144K sleep 21:10 0.00% kcfd 121 root 40 59 0 11M 6544K sleep 12:42 0.00% nscd 1 root 1 59 0 2576K 896K sleep 8:02 0.00% init 358 root 2 59 0 2296K 1432K sleep 7:46 0.00% apcupsd 9 root 19 59 0 10M 3976K sleep 5:28 0.00% svc.configd 575 root 1 59 0 0K 0K sleep 3:01 0.00% snmpd 238 root 16 59 0 15M 5448K sleep 2:08 0.00% fmd [[Para salir, pulsad la tecla Q]]Esta orden nos da mucha información adicional, de la que vamos a destacar: LWP (subprocesos o hilos del proceso), SIZE (tamaño total de la memoria del proceso), RES (tamaño de la memoria del proceso que está realmente en RAM), STATE (estado del proceso) y CPU (porcentaje de CPU usado por el proceso en estos momentos).
top
. Con eso, está
todo dicho (0.22% de CPU).
top
una orden muy usada por los administradores de sistemas. Si el
ordenador va muy lento, puede que sea porque algún proceso
se ha quedado colgado y consume mucha CPU o mucha memoria. En tal
caso, solamente tiene que localizarlo con top
y eliminarlo.
bash
.
bash
(Bourne again shell).
sleep
.
La probamos:
<gyermo@ENCINA>/usuarios/profes/gyermo$ sleep 5 [[...transcurridos 5 segundos...]] <gyermo@ENCINA>/usuarios/profes/gyermo$Esta orden la hemos lanzado en primer plano. La shell no nos va a devolver el control hasta que la orden acabe. Notad la diferencia con la ejecución siguiente:
<gyermo@ENCINA>/usuarios/profes/gyermo$ sleep 10 & [1] 21165 <gyermo@ENCINA>/usuarios/profes/gyermo$ ps PID TTY TIME CMD 19034 pts/1 0:00 ksh 21166 pts/1 0:00 ps 21165 pts/1 0:00 sleep <gyermo@ENCINA>/usuarios/profes/gyermo$ <gyermo@ENCINA>/usuarios/profes/gyermo$ <gyermo@ENCINA>/usuarios/profes/gyermo$ [1] + Done sleep 20 & <gyermo@ENCINA>/usuarios/profes/gyermo$Al lanzar un proceso en segundo plano, el proceso comienza a ejecutarse inmediatamente y, simultáneamente, la shell imprime el número de proceso de segundo plano que tiene entre corchetes y su PID, y nos devuelve el control para que podamos seguir trabajando. En el ejemplo, hemos dado la orden
ps
para observar el proceso de segundo plano y
ver que el PID coincide. Transcurridos los 10 segundos,
el proceso se muere (acaba) y la shell nos informa de ello
a la primera opción que tiene.
<gyermo@ENCINA>/usuarios/profes/gyermo$ sleep 60 & [1] 23285 <gyermo@ENCINA>/usuarios/profes/gyermo$ sleep 70 & [2] 23286 <gyermo@ENCINA>/usuarios/profes/gyermo$ sleep 80 & [3] 23287En la variable de entorno
$!
nos aparece el
PID del último proceso lanzado, por si nos resulta
de interés:
<gyermo@ENCINA>/usuarios/profes/gyermo$ echo $! 23287En cualquier momento, se puede preguntar por los procesos que tenemos en segundo plano con la orden
jobs
:
<gyermo@ENCINA>/usuarios/profes/gyermo$ jobs [3] + Running sleep 80 & [2] - Running sleep 70 & [1] Running sleep 60 &Si nos interesa conocer los PIDs de los procesos, disponemos de la opción
-l
de la orden jobs
.
kill
. Para referirnos a un proceso
de segundo plano, anteponermos a su número de
segundo plano el carácter de porcentaje:
<gyermo@ENCINA>/usuarios/profes/gyermo$ kill %2 <gyermo@ENCINA>/usuarios/profes/gyermo$ [2]- Terminated sleep 70 <gyermo@ENCINA>/usuarios/profes/gyermo$ jobs [1]- Running sleep 60 & [3]+ Running sleep 80 &Podemos, también, traer a primer plano un proceso de segundo plano, pero en ese caso, perdemos el control...
<gyermo@ENCINA>/usuarios/profes/gyermo$ fg %3 sleep 80 [[...pasado un rato...]] [1]- Done sleep 60 <gyermo@ENCINA>/usuarios/profes/gyermo$Por otro lado, a un proceso de primer plano, como hemos ya visto, se le puede matar con CTRL-C. Pero si en lugar de CTRL-C pulsamos CTRL-Z, podemos también recuperar el control y el proceso no muere. Solamente se queda parado:
<gyermo@ENCINA>/usuarios/profes/gyermo$ sleep 60 [[Pulsad aquí CTRL-Z]] [1]+ Stopped sleep 60 <gyermo@ENCINA>/usuarios/profes/gyermo$ jobs [1]+ Stopped sleep 60 <gyermo@ENCINA>/usuarios/profes/gyermo$A los procesos parados se les puede rearrancar, bien en primer plano con la orden
fg
, bien
en segundo plano con la orden bg
:
<gyermo@ENCINA>/usuarios/profes/gyermo$ jobs [1]+ Stopped sleep 60 <gyermo@ENCINA>/usuarios/profes/gyermo$ bg %1 [1]+ sleep 60 & <gyermo@ENCINA>/usuarios/profes/gyermo$ jobs [1]+ Running sleep 60 &
nohup
(No hang up):
nohup orden_que_queremos_que_no_muera &En cuanto a la orden
kill
, en realidad
sirve para enviar lo que se denominan señales.
Trataremos del asunto más adelante en estas
prácticas.
;
). La shell lo utiliza para
separar órdenes que tecleemos en una misma línea.
Por ejemplo, la siguiente línea hace que aparezcan las
dos palabras con un intervalo de 5 segundos entre ellas:
<gyermo@ENCINA>/usuarios/profes/gyermo$ echo Hola... ; sleep 5 ; echo ...caracola Hola... [[Transcurridos cinco segundos...]] ...caracolaPara lograr lo mismo, pero en segundo plano, se os puede ocurrir añadir un ampersand al final, pero esto no va a funcionar. El ampersand solo afectaría a la última orden, no al global de ellas. La shell permite agrupar órdenes mediante paréntesis. La solución consiste en combinar ambos:
<gyermo@ENCINA>/usuarios/profes/gyermo$ (echo Hola... ; sleep 5 ; echo ...caracola ) & Hola... [1] 743 <gyermo@ENCINA>/usuarios/profes/gyermo$ [[Transcurridos 5 segundos...]]...caracola
#!/bin/bash # Esto es un comentario. Los comentarios empiezan por almohadilla echo El número de parámetros pasados es $# echo Los parámetros son: $* echo El primer parámetro es $1 echo El segundo parámetro es $2 # Vamos a devolver un 0 a la shell exit 0Observad lo siguiente:
#
)#
*
1
, el segundo en 2
,
y así sucesivamenteexit
,
que acaba, en cualquier punto, con el programaexit
, el valor devuelto
es el de la última orden ejecutadaejemplo.sh
e
introducid el contenido del listado. Para ejecutarlo, simplemente
hay que dar el nombre del guion, como si de otra orden cualquiera
se tratase. Pero, ¡atención!:
<gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ ejemplo.sh bash: ./ejemplo.sh: Permission deniedPor defecto, los ficheros nuevos no se crean con el permiso de ejecución activado. Es por ello, que si los tratáis de ejecutar directamente, os va a dar un error de permisos. Pues los cambiamos:
<gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ ls -l ejemplo.sh -rw-r--r-- 1 gyermo profes 239 ago 26 17:37 ejemplo.sh <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ ejemplo.sh bash: ./ejemplo.sh: Permission denied <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ chmod 755 ejemplo.sh <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ ejemplo.sh El número de parámetros pasados es 0 Los parámetros son: El primer parámetro es El segundo parámetro es <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ ejemplo.sh hola adiós chimpún El número de parámetros pasados es 3 Los parámetros son: hola adiós chimpún El primer parámetro es hola El segundo parámetro es adiós <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo $? 0
umask
que,
de querer que sus efectos sean permanentes, se puede
incluir en el .bash_profile
. Aunque su efecto
es el de quitar permisos, no añadirlos. Se puede
usar para restringir los permisos concedidos por defecto
a ficheros y directorios recién creados.
Los interesados
pueden dirigirse a su página de manual.
shift
elimina el primer parámetro
y mueve una posición el resto hacia abajo. Se usa para
procesar los parámetros uno a uno en un bucle.
Modifiquemos el programa anterior para ver qué hace la
orden shift
:
#!/bin/bash # Esto es un comentario. Los comentarios empiezan por almohadilla echo ANTES DE SHIFT: echo El número de parámetros pasados es $# echo Los parámetros son: $* echo El primer parámetro es $1 echo El segundo parámetro es $2 echo shift echo DESPUÉS DE SHIFT: echo El número de parámetros pasados es $# echo Los parámetros son: $* echo El primer parámetro es $1 echo El segundo parámetro es $2 # Vamos a devolver un 0 a la shell exit 0Y el resultado de la ejecución:
<gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ ejemplo.sh hola adiós chimpún ANTES DE SHIFT: El número de parámetros pasados es 3 Los parámetros son: hola adiós chimpún El primer parámetro es hola El segundo parámetro es adiós DESPUES DE SHIFT: El número de parámetros pasados es 2 Los parámetros son: adiós chimpún El primer parámetro es adiós El segundo parámetro es chimpún
/dev/fd/n
. Así,
para sacar la palabra "Hola" por el canal de errores,
podemos escribirlo indistintamente:
<gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo "Hola" >&2 Hola <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo "Hola" >/dev/fd/2 HolaSi la shell tiene redireccionadas sus entradas o salidas, al escribir en ellas, el resultado irá a la correspondiente redirección. Pero la propia shell puede cambiar este comportamiento al vuelo, como se puede apreciar en el siguiente ejemplo, usando la orden
exec
:
<gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo "Salida normal" Salida normal <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ exec >salida.txt <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo "Salida cambiada" <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ exec >&2 <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ cat salida.txt Salida cambiadaEn el ejemplo hacemos que, a partir del primer
exec
,
la salida estándar esté redirigida al fichero
salida.txt
. De este modo, el mensaje del
echo
vemos que realmente no sale por la pantalla.
Una vez restaurada la salida estándar a la pantalla,
comprobamos cómo la salida en efecto se añadió
al fichero salida.txt
.
exec
permite trabajar con descriptores
más altos y esto, a su vez, permite trabajar con ficheros
como en cualquier otro lenguaje de programación. En
este ejemplo, abrimos un fichero, escribimos algo en él
y lo cerramos. Usaremos el descriptor número 7:
<gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ exec 7>salida.txt # Abrimos <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo "Prueba" >&7 # Escribimos <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ exec 7>&- # Cerramos <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ cat salida.txt PruebaEl problema puede venir al elegir nosotros un número de descriptor, que pudiera estar ocupado. Si dejamos este trabajo a la shell, lo haríamos así:
<gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ exec {FD}>salida.txt # Abrimos <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo "Prueba" >&$FD # Escribimos <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ exec {FD}>&- # Cerramos <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ cat salida.txt Prueba <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo El descriptor usado fue el $FD El descriptor usado fue el 10Hemos usado el signo de mayor que porque hemos querido abrir el fichero es modo de salida. Si lo hubiéramos querido abrir en modo de entrada, usaríamos el correspondiente signo de menor que y, si lo que deseamos es abrirlo para leer y escribir, la notación es:
exec {OTROFD}<>otroFichero.txt
.
exec 4>&10-
. Es evidente que si
el descriptor 10 no está abierto por el proceso (no existe
para él), pues nos dará error.
rwxr-x---
. Probadla con un fichero, con varios
y con expresiones regulares para ver que funciona como se
espera.
read
read
. Lo introducido por el
usuario aparece en la variable de entorno REPLY
:
<gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ read Hola, ¿qué tal? <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo $REPLY Hola, ¿qué tal?
<gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ PALABRA=salamanquesa <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo ${PALABRA:4:7} manques <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo ${PALABRA:7} quesaPara saber la longitud de la cadena, se usa:
<gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo ${#PALABRA} 12Las cuatro posibilidades que vienen a continuación, sirven para suprimir el inicio o el fin de la cadena. Usan expresiones regulares y la diferencia entre las dos versiones es que una suprime lo máximo que case (la que tiene dos caracteres) y la otra suprime lo mínimo que case (la que tiene un carácter), como en los siguientes ejemplos:
<gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo ${PALABRA%a*} salamanques <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo ${PALABRA%%a*} s <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo ${PALABRA#*[lq]} amanquesa <gyermo@ENCINA>/usuarios/profes/gyermo/PRIVADO$ echo ${PALABRA##*[lq]} uesaTambién tenemos posibilidad de efectuar sustituciones en general, basándonos o no, en expresiones regulares:
<gyermo@ENCINA</usuarios/profes/gyermo/PRIVADO$ echo ${PALABRA/ques/c} salamanca <gyermo@ENCINA</usuarios/profes/gyermo/PRIVADO$ echo ${PALABRA/*e/ca} casaAunque existen algunas posibilidades más, como en el resto de estas prácticas, nos hemos centrado solamente en las más útiles. Para saber más, se puede consultar la página de manual de
bash
.
.gif
ps
top
sleep
jobs
kill
fg
bg
exit
shift
read