- basic: funcionalidades básicas
- multi-pipe: múltiples tuberías
- background: procesos ejecutándose en segundo plano
- spaces: comandos con cualquier cantidad de espacios
- history: historial de comandos
- help: descripción de las funcionalidades del shell
- cd: cambia de direcciones
- exit: termina el shell
- history: muestra el historial
- fg: devuelve al foreground un proceso del background
- again: ejecuta un comando del historial
- help: muestra la ayuda
- jobs: muestra todos los jobs en cola
Para ver la descripción de todos estos built-in ejecute el comando help --all
o para ver uno en específico help <commando>
Nuestro shell usa una estructura llamada job que tiene los siguiente campos:
int id
-> Id del jobint count_kill
-> La cantidad de señales SIGINT que ha recibido el jobstruct process* root
-> Primer proceso del jobchar* command
-> La línea de comando del jobpid_t pgid
-> Id del grupo de procesos al que pertenece el jobint mode
-> Modo de ejecución en el que tiene que ejecutarse el job: pipeline, background,foregroundint save
-> Indica si el jobs hay que salvarlo en el historial
Nuestro shell usa una estructura llamada process que tiene lo siguientes campos:
char* command
-> El comando del procesoint argc
-> Cantidad de parámetros que recibe el procesochar** argv
-> Parámetros que recibe el procesochar* input_path
-> La dirección del archivo donde se obtiene la entrada del proces, en caso de existirchar* output_path
-> La dirección del archivo donde se redirige la salida del proceso, en caso de existirpid_t pid
-> Pid del procesoint type
-> Tipo de proceso: externos y built-inint status
-> Estado en el que está el procesostruct process* next
-> Proceso siguiente
Nuestro shell utiliza una estructura info_shell que tiene los siguientes campos:
int pid
-> El pid del shellchar* cur_dir
-> La dirección actual del shellstruct job** jobs
-> Todos los jobs que están en el shelllist* back_id
-> Almacena los índices que tienen los jobs según el orden en que fueron introducidos en la lista jobs
Nuestro shell permite el ingreso del comando history
:
- Cuando se ingresa el comando
history
este devuelve los últimos 10 comandos ingresados en el shell incluyendo el propio history. - Permite además que la salida del comando history sea guardado en un archivo. (Redirección de salida)
- Al iniciarse el shell este carga los comando ingresados anteriormente history.dat que se encuentra en la dirección /home/user. De esta forma si el shell se cierra y se vuelve abrir el historial de comandos no se pierde. En caso de que al inicio del shell este archivo no se encuentre entonces el historial del shell estará vacío.
- Mientras el shell se este ejecutando el historial de comandos se guarda en una estructura interna del shell llamada info_shell. Si el shell se cierra normalente entonces la información guardada en info_shell se guarda en el archivo history.dat pero si el shell se cierra debido a un comportamiento inesperado entonces el historial de comandos que está en info_shell no se guarda en el archivo history.dat por lo que en este queda el historial de comandos del último shell que se cerro sin errores inesperados.
Supongamos que el historial de comandos está vacío, que tenemos el shell abierto y hacemos:
$echo HelloWorld!
HelloWorld!
$history
[1]: echo HelloWorld!
[2]: history
Primero se ingresa y se ejecuta el comando echo HelloWorld!
y luego ingresamos history
y se obtiene los últimos 2 comandos ingresados puesto que solo se han ingresados 2 comandos.
Supongamos que tenemos el siguiente historial:
[1]: ls
[2]: python3 &
[3]: bash &
[4]: fg 1
[5]: python3 &
[6]: fg
[7]: history
[8]: ls | more
[9]: exit
[10]: history
Si hacemos:
$echo HelloWorld!
HelloWorld!
$history
[1]: bash &
[2]: fg 1
[3]: python3 &
[4]: fg
[5]: history
[6]: ls | more
[7]: exit
[8]: history
[9]: echo HelloWorld!
[10]: history
Obsérvese que los dos primeros comandos ya no están, el resto de los que estaban, disminuyeron su índice en dos y entraron dos nuevos comandos al final echo HelloWorld!
y history
.
Nuestro shell permite que se ingrese el comando cd
:
- Si
cd
no viene acompañado de número parámetro entonces la dirección del shell se cambia a /home/user y la misma se guarda en una estructura interna del shell llamada info_shell, para poder ser usada posteriormente en otros procesos. - Si
cd
viene acompañado de una dirección válida, o sea que sea una dirección correcta y sea interna a la dirección actual, entonces la dirección del shell cambia a dicha dirección y como en el caso anterior también se almacena en la estructura interna info_shell. - Si
cd
viene acompañado de un parámetro y este empieza con~
se concatenan /home/user y el resto del parámetro sin contar el caracter~
y de ser válida esta cadena como dirección, el shell cambia a esta dirección y se guarda en la estructura info_shell. - Si
cd
viene acompañado de una dirección inválida entonces el shell imprime ERRORcd: <dir>
: No such file or directory.
Nuestro shell permite implementar el comando fg
:
- Si se ingresa
fg
sin parámetros entonces se trae al foreground el último job enviado al background. En caso de que no haya ningún job en background se imprime Error: No such job in background. - Si se ingresa
fg
con un índice se chequea que es un índice válido, o sea que es un índice entre 1 y la cantidad de jobs que estám en la lista jobs en background. En caso del índice ser incorrecto, o sea que no están en el rango de entre 1 y la cantidad de jobs en background se imprime ERRORfg <index>
: No such job. - Para ambos casos luego de ya saber que job se va a ejecutar en foreground, a este job se le envían la señal "SIGCONT" para que el job se ejecute. Entonces se remueve el job de la lista jobs en background y se espera que el job termine de ejecutarse, devolviendole el control al shell.
$ python3 &
$ bash &
$ fg 1
>>>
Primero se manda a python3
al background, luego se manda a bash
al background y se trae a python3
al foreground ya que está en el índice 1.
$ python3 &
$ bash &
$ fg
$ bash $
Primero se manda a python3 al background, luego se manda a bash al background y se trae a bash al foreground ya que fue el último job en mandarse a background.
Nuestro shell permite ingresar el comando jobs
:
- Este comando permite recorrer los jobs que se encuentran en la lista de jobs en background e imprime el indice que ocupa en dicha lista, su
back_id
es el id que tiene como job en dicha lista y el estado en que se encuentra en dicho job - Su puede guardar la salida de este comando en un archivo, o sea jobs
>
a es un comando valido - Si no hay jobs en el background imprime No jobs in background
Nuestro shell permite que se le ingrese el comando again <index>
:
- Primero se chequea que sea un índice válido y en caso de no serlo se imprime ERROR Index out of range of history.
- Si el índice es válido entonces se busca en el historial y el comando correspondiente se guarda en el mismo y se ejecuta.
- Si no se pone ningún número entonces se imprime ERROR No Index
Supongamos que tenemos el siguiente historial:
[1]: ls -la --color=never | wc
[2]: echo HelloAgain
[3]: ls -la | cat
[4]: history
[5]: exit
[6]: history
[7]: history
[8]: echo a
[9]: exit
[10]: history
Si introducimos again 8
entonces se ejecuta el comando echo a
y el historial queda de la siguiente forma:
[1]: echo HelloAgain
[2]: ls -la | cat
[3]: history
[4]: exit
[5]: history
[6]: history
[7]: echo a
[8]: exit
[9]: history
[10]: echo a
Nota: No funciona con tuberías
Cierra el shell y salva el historial en el archivo history.dat. El archivo history.dat es donde se guardan los comandos que se han ido introduciendo.
- Ariel Alfonso Triana Pérez (ArielTriana)
- Carlos Toledo Silva (CTS-crypto)