Lo que tenemos es un fichero en MSDOS llamado fichero.txt que queremos renombrar a fichero$dia$mes$anyo.txt. El siguiente script lo hace:
rem @echo off
for /f "tokens=1-3 delims=/" %%i in ('echo %DATE%') do (
set dia=%%i
set mes=%%j
set any=%%k
)
rename fichero.txt fichero%dia%%mes%%any%.txt
Es posible que, dependiendo del shell, el valor de 'dia' nos proporcione el dia de la semana.
En ese caso, simplemente obtenemos un nuevo valor:
rem @echo off
for /f "tokens=1-3 delims=/" %%i in ('echo %DATE%') do (
set diasem=%%i
set dia=%%j
set mes=%%k
set any=%%l
)
rename fichero.txt fichero%dia%%mes%%any%.txt
9 de septiembre de 2004, 14:08
Tenemos un array que acabamos de definir, y queremos pasarselo a una funcion para que lo rellene. Esto se hará de la siguiente forma (se incluye algo más de código pero es sencillo):
Primero, abrimos un fichero, inicializamos una vector llamado mi_array, y le pasamos a la función dos parámetros: una cadena de texto y el vector. Destacar la forma de pasar el array: @el_vector
Después, en la función, lo que haremos será extraer los parámetros (tener en cuenta que si el último parámetro pasado es un vector, siempre el resto de parámetros deben de ir antes, para que la función conozca en que posición se encuentran), recorrer un fichero e ir insertando cada linea leida en el array. Destacar aqui:
1) La forma de extraer el vector: No con '@', sino con '$'
2) Como refenciamos el array al realizar el push: @{$variable_del_array}
El código:
...
# Abrimos un fichero
open(CFFILE,"< mifile") or die "ERROR: open() n";
# Inicializo el array
@mi_array=();
# Llamamos a la funcion
mi_funcion("una cadena", @mi_array);
...
sub mi_funcion{
# Extraigo los parametros.
($message, $mi_array) = @_;
print "$message n";
# Recorremos el fichero leido
while(){
# Quitamos el salto de linea
chomp($_);
push(@{$mi_array},$_);
}
}
...
Y eso es todo. Sencillo, ¿no?
Problema: recibimos en una cuenta de correo unix una imagen en base64, y queremos pasarla a binario, para mostrarla en la web.
Necesitaremos Perl:
perl -MMIME::Base64 -ne 'print decode_base64($_)' < message > message.jpg
Siendo 'message' el texto con codificacion base64 que hemos recibido en nuestro correo.
Estas son algunas de las operaciones básicas sobre el ldap. No voy a entrar a configurar el LDAP ni discutir como se puede crear el arbol, sino que me basaré en una estructura ya dada. Obviamente, más informacion puede obtenerse de las páginas de manual del LDAP y de la propia documentación de la herramienta, entre otros, y esto no pretende ser una lista exhaustiva de todos los casos, sino un acceso rápido a los comandos más utilizados.
Todo lo que sigue se proporciona, como es obvio, sin ninguna garantía, por lo que estoy, como es obvio exento de responsabilidad de los efectos que dichas instrucciones puedan tener sobre tu sistema.
Le cuestión es, a partir de una configuración samba totalmente funcional, crear un nuevo usuario que tenga acceso a nuevos recursos. No se mucho -casi nada- de samba, pero los pasos básicos serían (linux debian, pero no debería variar demasiado):
1) Crear el usuario de sistema (# adduser usuario1). El password que se le de no tiene porqué coincidir con el del usuario samba que crearemos.
2) Añadir el usuario al smbusers (normalmente /etc/samba/smbusers). Tener en cuenta que el formato de las líneas es "usuario_sistema= usuario_samba1 usuario_samba2...", y que no es necesario que los usuarios del samba existan (pero si el de sistema). Es decir,
usuario1= smbuser1
3) Crear los recursos en /etc/samba/smb.conf (generalmente):
[recurso_nuevo] comment = Un nuevo recurso writable = yes locking = no path = /usr/local/apache/htdocs/nuevo_recurso public = yes valid users = smbuser1
(Ejemplo genérico)
4) Asignarle un password al usuario (# smbpasswd -a smbuser1). Este no tiene (no debería, de hecho) coincidir con el del usuario de sistema sobre el que se mapea este usuario samba.
5) Darle los permisos necesarios al usuario de sistema usuario1 (pero no al usuario del samba, ya que el sistema de ficheros no conoce a los usuarios del samba) sobre /usr/local/apache/htdocs/nuevo_recurso.
Esta solución surgió ante el problema de cómo saber que la recuperación por TSM de una estructura de directorios de unas ciertas dimensiones (en este caso, >100MB) se había realizado de forma completa sobre otro directorio de la misma máquina. Lo que nos interesaba era saber principalmente si se habían recuperado todos los directorios y ficheros con el tamaño original.
En un principio, parecía que la opción -s junto con --block-size=1 sería suficiente, pero como pone en el info:
`--size' Print the disk allocation of each file to the left of the file name. This is the amount of disk space used by the file, which is usually a bit more than the file's size, but it can be less if the file has holes.
Por lo que esta opción no es válida, ya que no imprime el tamaño "real" del fichero. Se escogió en su lugar por filtrar la salida del ls, sacarla a un fichero y pasarle diff a ambos, para ver las posibles discrepancias:
El formato del ls -al en este caso (linux debian, ls (fileutils) 4.1) es el siguiente:
woo:~# ls -al total 56 drwxr-xr-x 5 root root 4096 dic 10 10:58 . drwxr-xr-x 21 root root 4096 dic 4 17:21 .. -rw------- 1 root root 10643 dic 9 19:07 .bash_history -rw-r--r-- 1 root root 410 sep 6 1998 .bashrc drwxr-xr-x 2 root root 4096 jun 11 13:06 test -rw------- 1 root root 1248 jun 13 07:26 test2 -rw-r--r-- 1 root root 202 dic 21 1999 .profile drwx------ 2 root root 4096 jun 6 2003 .ssh drwxr-xr-x 3 root root 4096 dic 10 10:09 temp -rw------- 1 root root 11061 dic 10 10:55 .viminfo woo:~#
Puesto que nos interesan los campos 1 (permisos) , 3 y 4 (propietarios), 5 (tamaño), y 9 (nombre), tendríamos que hacer lo siguiente:
woo:/dir1# ls -laR | awk '{print $1" "$3" "$4" "$5" "$9}' >/tmp/dir1
woo:/dir2# cd /dir2
woo:/dir2# ls -laR | awk '{print $1" "$3" "$4" "$5" "$9}' > /tmp/dir2
woo:/dir1# cd /tmp
woo:/tmp# diff dir1 dir2
woo:/tmp#
Obviamente, en caso de que faltasen ficheros o directorios, la salida del diff sería algo más compleja y es posible que intratable, dependiendo de las posibles diferencias. Digamos que este método únicamente sirve en caso de que estemos bastante seguros de que se han recuperado todos los ficheros, pero queramos también estar seguros de que el tamaño de todos ellos es el mismo.
Nota: La salida del ls puede variar si se realiza sobre máquinas con distinto S.O.
Este problema me surgió a raíz de unas copias con TSM (Tivoli Storage Manager, creo), en las que era necesario copiar ficheros que contenían acentos, diéresis y eñes:
12/10/03 10:16:51 fioScanDirEntry(): Object '/root/niño.gif' contains unrecognized symbols for current locale, skipping...
Vamos a asumir que queremos instalar el locale que nos permita reconocer estos caracteres además del euro, es decir el es_ES@euro.
Lo que se hizo fue:
1) Editamos /etc/locale.gen, metiendo las siguientes líneas:
es_ES ISO-8859-15 es_ES@euro ISO-8859-15 en_US ISO-8859-1
2) Ejecutamos locale-gen:
woo:~# locale-gen Generating locales... es_ES.ISO-8859-15... done es_ES.ISO-8859-15@euro... done en_US.ISO-8859-1... done Generation complete. woo:~#
3) Ahora, ya podemos utilizar este locale (dejamos LANGUAGE como en_US para que las páginas man salgan en inglés):
woo:~# LC_ALL=es_ES@euro woo:~# LANG=es_ES.ISO-8859-15 woo:~# LANGUAGE=en_US woo:~# export LC_ALL LANG LANGUAGE
4) Adicionalmente, pueden meterse estas variables en /etc/environment, aunque no se si este fichero es dependiente de Debian. En este caso en concreto, se metieron dichas variables en el script que arrancaba el scheduler.
Como nota adicional, se comentaba por ahí que era necesario reiniciar (¿?) para que surtiesen efecto todos los cambios, pero puesto que en mi caso no era necesario, no se hizo.
Sea el siguiente código:
cat $file | while read line; do exit done echo "Esto no debería salir"
En principio, no debería ejecutarse el último echo, aunque como puede comprobarse, sí que se imprime. Lo que sucede es que el while read line crea un subshell, y el exit únicamente sale de dicho subshell. La solución es hacer que el exit devuelva un valor, y posteriormente comprobar el valor de retorno. Si ambos son iguales, ejecutar un exit después del bucle. Es decir:
cat $file | while read line; do exit 9 done if [ "$?" == "9" ]; then exit fi echo "Esto no sale"
Ejecutar el siguiente script:
#!/bin/bash
T='gYw' # The test text
echo -e "n 40m 41m 42m 43m\
44m 45m 46m 47m";
for FGs in ' m' ' 1m' ' 30m' '1;30m' ' 31m' '1;31m' ' 32m' \
'1;32m' ' 33m' '1;33m' ' 34m' '1;34m' ' 35m' '1;35m' \
' 36m' '1;36m' ' 37m' '1;37m';
do FG=${FGs// /}
echo -en " $FGs 033[$FG $T "
for BG in 40m 41m 42m 43m 44m 45m 46m 47m;
do echo -en "$EINS 033[$FG033[$BG $T 033[0m";
done
echo;
done
echo
Básicamente lo que hace es imprimir una especie de tabla con cada celda con un fondo y un color de letra.
La forma de acceder a variables de entorno en el awk es la que se muestra en el siguiente ejemplo:
sebastian@woo~$ total=2
sebastian@woo~$ export total
sebastian@woo~$ echo "p1 p2 p3" | awk '{print $(ENVIRON["total"])}'
p2
sebastian@woo~$
En caso de tener problemas con determinados shell-scripts, en el bash se dispone del "comando" set -x, que proporciona información sobre todos los comandos ejecutados y sus argumentos. Esto es útil en caso de no tener claro qué parámetros o cómo está funcionando por ejemplo un awk.
Ejemplo:
sebastian@woo:~$ set -x sebastian@woo:~$ ls + ls --color=auto ala.css index.html print.css sebastian@woo:~$ set +x + set +x sebastian@woo:~$ ls ala.css index.html print.css
Ver las entradas precedidas por un "+", que son las que proporciona el 'set -x'. Como puede verse, se deshabilita con un 'set +x'. Esta pareja (-x, +x) puede colocarse en cualquier lugar de un script, por lo que se puede restringir la obtención de esta información a un determinado comando o a unos pocos y no necesariamente a todo el fichero.
Sea un shell-script en el que debemos leer un fichero línea a línea y adicionalmente, responder a una serie de preguntas tras cada entrada. El problema se presenta si se hace de la siguiente manera:
cat $file | while read line; do echo $line echo -n "¿Correcto? " read ans done
En este caso, en $ans tenemos ya la siguiente entrada del fichero, por lo que nunca se llega a leer la respuesta a la pregunta. La solución es redirigir la salida del fichero a un nuevo descriptor de fichero, en este caso el 5:
while read line <&5 ; do
entrada=`echo $line | awk -F; '{print $2}'`
echo -n "¿Correcto? "
read ans
done 5<$file
De este modo, la lectura del fichero y de las respuestas se hacen en descriptores de ficheros distintos, por lo que no hay interferencia entre ellos.
Si lo que queremos es cambiar el modo de funcionamiento o la velocidad de un interfaz de red en Linux, utilizaremos la herramienta mii-tool.
mimachine:~# mii-tool --help
usage: mii-tool [-VvRrwl] [-A media,... | -F media] [interface ...]
-V, --version display version information
-v, --verbose more verbose output
-R, --reset reset MII to poweron state
-r, --restart restart autonegotiation
-w, --watch monitor for link status changes
-l, --log with -w, write events to syslog
-A, --advertise=media,... advertise only specified media
-F, --force=media force specified media technology
media: 100baseT4, 100baseTx-FD, 100baseTx-HD, 10baseT-FD, 10baseT-HD,
(to advertise both HD and FD) 100baseTx, 10baseT
mimachine:~#
Su funcionamiento se deja como ejercicio al lector :)